From 64c919cefbedfd6432182e1bab0eab765f919150 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 5 Dec 2024 15:50:48 +0100
Subject: [PATCH 01/55] new page for details created, routing set on click of
 record title

---
 src/app/[locale]/details/page.tsx             | 27 +++++++++++++++++++
 src/components/app/results/ListResults.tsx    |  8 +++++-
 .../app/results/ListResults/ResultItem.tsx    | 16 ++++++++---
 3 files changed, 46 insertions(+), 5 deletions(-)
 create mode 100644 src/app/[locale]/details/page.tsx

diff --git a/src/app/[locale]/details/page.tsx b/src/app/[locale]/details/page.tsx
new file mode 100644
index 0000000..fcb6ef2
--- /dev/null
+++ b/src/app/[locale]/details/page.tsx
@@ -0,0 +1,27 @@
+"use client";
+
+import { useSearchParams } from "next/navigation";
+import React, { Suspense } from "react";
+
+const DetailsComponent = () => {
+  const resultParams = useSearchParams();
+  const category = resultParams.get("category");
+  const searchText = resultParams.get("searchText") ?? undefined;
+  const detailsText = resultParams.get("detailsText") ?? undefined;
+
+  return (
+    <>
+      <div>{category}</div>
+      <div>{searchText}</div>
+      <div>{detailsText}</div>
+    </>
+  );
+};
+
+export default function Details() {
+  return (
+    <Suspense>
+      <DetailsComponent />
+    </Suspense>
+  );
+}
diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index 824254d..5a5f38e 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -141,7 +141,13 @@ const ListResultsComponent = ({ activeCategory }: Props) => {
               <div className="flex flex-col py-5 xl:py-8">
                 {results.length ? (
                   results.map((item: ResultItemType) => (
-                    <ResultItem key={item.id} item={item} idx={item.id} />
+                    <ResultItem
+                      key={item.id}
+                      item={item}
+                      idx={item.id}
+                      activeCategory={activeCategory}
+                      searchText={searchText}
+                    />
                   ))
                 ) : (
                   <NoResults />
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index f097bd3..c3b5ec1 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -7,14 +7,17 @@ import ExternalLink from "@/components/ExternalLink";
 import Relationships from "@/components/app/results/ListResults/ResultItem/Relationships";
 import { Link } from "@/i18n";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
-import type { ResultItem as ResultItemType } from "@/types/types";
+import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
+import type { Category, ResultItem as ResultItemType } from "@/types/types";
 
 type Props = {
   item: ResultItemType;
   idx: string;
+  searchText: string | undefined;
+  activeCategory: Category;
 };
 
-const ResultItem = ({ item, idx }: Props) => {
+const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
   const t = useTranslations("ResultItem");
   const s = useTranslations("BackendIds");
   const descRef = useRef<HTMLParagraphElement>(null);
@@ -98,7 +101,10 @@ const ResultItem = ({ item, idx }: Props) => {
       key={idx}
       className="my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white"
     >
-      <div className="inline-flex align-middle items-center pb-2">
+      <Link
+        className="inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau h-5 hover:transition-all hover:translate-x-3"
+        href={`/details?category=${activeCategory.id}${searchText ? `&searchText=${searchText}` : ``}&detailsText=${item.name}`}
+      >
         {titleIconHref ? (
           <span className="mr-1">
             <Image
@@ -113,7 +119,9 @@ const ResultItem = ({ item, idx }: Props) => {
         <div className="font-semibold" rel="noreferrer">
           {item.name}
         </div>
-      </div>
+        <RightArrowIcon />
+      </Link>
+
       <div className="text-sm">
         <span className="font-semibold">{s("txt_identifier")}: </span>
         {displayLinkItem(item.txt_identifier ?? item.id)}
-- 
GitLab


From 9d4b6f1c456f3b21b8ab251a4d3096b99de9fff7 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 12 Dec 2024 19:33:03 +0100
Subject: [PATCH 02/55] made details a sub-result and implemented simple
 reducer and context based state handling (not working)

---
 src/app/[locale]/details/page.tsx             | 27 -------------
 src/app/[locale]/results/details/page.tsx     | 38 +++++++++++++++++++
 .../app/results/Details/DetailsItemCard.tsx   | 33 ++++++++++++++++
 .../app/results/ListResults/ResultItem.tsx    | 33 +++++++++++++---
 src/context/detailsItem.tsx                   | 22 +++++++++++
 5 files changed, 120 insertions(+), 33 deletions(-)
 delete mode 100644 src/app/[locale]/details/page.tsx
 create mode 100644 src/app/[locale]/results/details/page.tsx
 create mode 100644 src/components/app/results/Details/DetailsItemCard.tsx
 create mode 100644 src/context/detailsItem.tsx

diff --git a/src/app/[locale]/details/page.tsx b/src/app/[locale]/details/page.tsx
deleted file mode 100644
index fcb6ef2..0000000
--- a/src/app/[locale]/details/page.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-"use client";
-
-import { useSearchParams } from "next/navigation";
-import React, { Suspense } from "react";
-
-const DetailsComponent = () => {
-  const resultParams = useSearchParams();
-  const category = resultParams.get("category");
-  const searchText = resultParams.get("searchText") ?? undefined;
-  const detailsText = resultParams.get("detailsText") ?? undefined;
-
-  return (
-    <>
-      <div>{category}</div>
-      <div>{searchText}</div>
-      <div>{detailsText}</div>
-    </>
-  );
-};
-
-export default function Details() {
-  return (
-    <Suspense>
-      <DetailsComponent />
-    </Suspense>
-  );
-}
diff --git a/src/app/[locale]/results/details/page.tsx b/src/app/[locale]/results/details/page.tsx
new file mode 100644
index 0000000..c3f2ab5
--- /dev/null
+++ b/src/app/[locale]/results/details/page.tsx
@@ -0,0 +1,38 @@
+"use client";
+
+import React, { Suspense, useReducer } from "react";
+
+import BackBar from "@/components/app/results/BackBar";
+import DetailsItemCard from "@/components/app/results/Details/DetailsItemCard";
+import {
+  detailsReducer,
+  DetailsItemContext,
+  DetailsItemDispatchContext,
+} from "@/context/detailsItem";
+
+const DetailsComponent = () => {
+  // this component needs and uses the detailsItemContext
+  const [detailsItem, dispatch] = useReducer(detailsReducer, {});
+
+  //const resultParams = useSearchParams();
+  // const category = resultParams.get("category") as string;
+  // const searchText = resultParams.get("searchText") ?? undefined;
+  // const detailsText = resultParams.get("detailsText") ?? undefined;
+
+  return (
+    <DetailsItemContext.Provider value={detailsItem}>
+      <DetailsItemDispatchContext.Provider value={dispatch}>
+        <BackBar />
+        <DetailsItemCard />
+      </DetailsItemDispatchContext.Provider>
+    </DetailsItemContext.Provider>
+  );
+};
+
+export default function Details() {
+  return (
+    <Suspense>
+      <DetailsComponent />
+    </Suspense>
+  );
+}
diff --git a/src/components/app/results/Details/DetailsItemCard.tsx b/src/components/app/results/Details/DetailsItemCard.tsx
new file mode 100644
index 0000000..99cd257
--- /dev/null
+++ b/src/components/app/results/Details/DetailsItemCard.tsx
@@ -0,0 +1,33 @@
+"use client";
+import React, { useContext, useState, useEffect } from "react";
+
+import { DetailsItemContext } from "@/context/detailsItem";
+import { ResultItem } from "@/types/types";
+
+const DetailsItemCard = () => {
+  const detailsItemFromReducer = useContext<ResultItem | object>(DetailsItemContext);
+  const [detailsItem, setDetailsItem] = useState<ResultItem | null>(null);
+
+  useEffect(() => {
+    console.log("In details card:", detailsItemFromReducer);
+    const isResultItem = (obj: object | ResultItem): obj is ResultItem =>
+      Object.keys(detailsItemFromReducer).length > 0;
+
+    if (isResultItem(detailsItemFromReducer)) {
+      setDetailsItem(detailsItemFromReducer);
+    }
+  }, [detailsItemFromReducer]);
+
+  return (
+    <>
+      {detailsItem ? (
+        <>
+          <div>{detailsItem.name}</div>
+          <div>{detailsItem.id}</div>
+        </>
+      ) : null}
+    </>
+  );
+};
+
+export default DetailsItemCard;
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index c3b5ec1..fa6ca19 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -1,10 +1,14 @@
+"use client";
+
 import Image from "next/image";
+import { useRouter } from "next/navigation";
 import { useTranslations } from "next-intl";
-import { useEffect, useRef, useState } from "react";
+import { useEffect, useRef, useState, useReducer } from "react";
 
 import { INSTITUTE_ROR_LOGOS } from "@/app/api/config/config";
 import ExternalLink from "@/components/ExternalLink";
 import Relationships from "@/components/app/results/ListResults/ResultItem/Relationships";
+import { detailsReducer } from "@/context/detailsItem";
 import { Link } from "@/i18n";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
@@ -13,13 +17,18 @@ import type { Category, ResultItem as ResultItemType } from "@/types/types";
 type Props = {
   item: ResultItemType;
   idx: string;
-  searchText: string | undefined;
-  activeCategory: Category;
+  searchText?: string;
+  activeCategory?: Category;
 };
 
 const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
+  // create a item context
+  // const detailsItemContext =  createContext(item)
+  const [detailsItem, dispatch] = useReducer(detailsReducer, {});
+  const router = useRouter();
   const t = useTranslations("ResultItem");
   const s = useTranslations("BackendIds");
+
   const descRef = useRef<HTMLParagraphElement>(null);
   const [descShowMore, setDescShowMore] = useState(false);
   const [descShowReadMore, setDescShowReadMore] = useState(false);
@@ -96,14 +105,26 @@ const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
     return filteredArr.length > 0 ? <Relationships filteredArr={filteredArr} type={type} /> : null;
   };
 
+  const handleOnClick = () => {
+    console.log("current detailsItem:", detailsItem);
+    // action object
+    dispatch({
+      type: "setDetailsRequested",
+      item,
+    });
+    router.push(
+      `/results/details?category=${activeCategory?.id}${searchText ? `&searchText=${searchText}` : ``}&detailsText=${item.id}`
+    );
+  };
+
   return (
     <div
       key={idx}
       className="my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white"
     >
-      <Link
+      <button
         className="inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau h-5 hover:transition-all hover:translate-x-3"
-        href={`/details?category=${activeCategory.id}${searchText ? `&searchText=${searchText}` : ``}&detailsText=${item.name}`}
+        onClick={handleOnClick}
       >
         {titleIconHref ? (
           <span className="mr-1">
@@ -120,7 +141,7 @@ const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
           {item.name}
         </div>
         <RightArrowIcon />
-      </Link>
+      </button>
 
       <div className="text-sm">
         <span className="font-semibold">{s("txt_identifier")}: </span>
diff --git a/src/context/detailsItem.tsx b/src/context/detailsItem.tsx
new file mode 100644
index 0000000..d769b22
--- /dev/null
+++ b/src/context/detailsItem.tsx
@@ -0,0 +1,22 @@
+"use client";
+
+import { createContext } from "react";
+
+import { ResultItem } from "@/types/types";
+
+export const detailsReducer = (
+  detailsItem: ResultItem | object,
+  action: { type: "setDetailsRequested" | "getDetailsRequested"; item?: ResultItem }
+) => {
+  switch (action.type) {
+    case "setDetailsRequested":
+      return { ...action.item };
+    case "getDetailsRequested":
+      return detailsItem !== null ? { ...detailsItem } : {};
+    default:
+      throw Error("Unknown action:", action.type);
+  }
+};
+
+export const DetailsItemContext = createContext<ResultItem | object>({});
+export const DetailsItemDispatchContext = createContext<ResultItem | object | null>(null);
-- 
GitLab


From 406565c308bea3bb23d9dc78a2e88b0b0b4bb829 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Fri, 13 Dec 2024 12:54:08 +0100
Subject: [PATCH 03/55] used jotai to share state on navigating to new view,
 shows selected result details

---
 package-lock.json                             |   27 +-
 package.json                                  |    1 +
 src/app/[locale]/results/details/page.tsx     |   34 +-
 .../app/results/Details/DetailsItemCard.tsx   |   32 +-
 .../app/results/ListResults/ResultItem.tsx    |   30 +-
 src/context/detailsItem.tsx                   |   22 -
 src/state/atoms.tsx                           |    5 +
 yarn.lock                                     | 1728 ++++++++---------
 8 files changed, 912 insertions(+), 967 deletions(-)
 delete mode 100644 src/context/detailsItem.tsx
 create mode 100644 src/state/atoms.tsx

diff --git a/package-lock.json b/package-lock.json
index 3ac9a93..2ea095f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
       "dependencies": {
         "@headlessui/react": "^1.7.18",
         "@headlessui/tailwindcss": "^0.1.3",
+        "jotai": "^2.10.3",
         "next": "14.1.0",
         "next-intl": "^3.19.1",
         "react": "^18",
@@ -2287,7 +2288,7 @@
     },
     "node_modules/@types/prop-types": {
       "version": "15.7.12",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/@types/qs": {
@@ -2302,7 +2303,7 @@
     },
     "node_modules/@types/react": {
       "version": "18.3.2",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT",
       "dependencies": {
         "@types/prop-types": "*",
@@ -3445,7 +3446,7 @@
     },
     "node_modules/csstype": {
       "version": "3.1.3",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/damerau-levenshtein": {
@@ -6369,6 +6370,26 @@
         "jiti": "bin/jiti.js"
       }
     },
+    "node_modules/jotai": {
+      "version": "2.10.3",
+      "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.10.3.tgz",
+      "integrity": "sha512-Nnf4IwrLhNfuz2JOQLI0V/AgwcpxvVy8Ec8PidIIDeRi4KCFpwTFIpHAAcU+yCgnw/oASYElq9UY0YdUUegsSA==",
+      "engines": {
+        "node": ">=12.20.0"
+      },
+      "peerDependencies": {
+        "@types/react": ">=17.0.0",
+        "react": ">=17.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "react": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/js-tokens": {
       "version": "4.0.0",
       "license": "MIT"
diff --git a/package.json b/package.json
index efac38f..37f7a7a 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
   "dependencies": {
     "@headlessui/react": "^1.7.18",
     "@headlessui/tailwindcss": "^0.1.3",
+    "jotai": "^2.10.3",
     "next": "14.1.0",
     "next-intl": "^3.19.1",
     "react": "^18",
diff --git a/src/app/[locale]/results/details/page.tsx b/src/app/[locale]/results/details/page.tsx
index c3f2ab5..a2f90dd 100644
--- a/src/app/[locale]/results/details/page.tsx
+++ b/src/app/[locale]/results/details/page.tsx
@@ -1,31 +1,27 @@
 "use client";
 
-import React, { Suspense, useReducer } from "react";
+import { useSearchParams } from "next/navigation";
+import React, { Suspense } from "react";
 
 import BackBar from "@/components/app/results/BackBar";
 import DetailsItemCard from "@/components/app/results/Details/DetailsItemCard";
-import {
-  detailsReducer,
-  DetailsItemContext,
-  DetailsItemDispatchContext,
-} from "@/context/detailsItem";
 
-const DetailsComponent = () => {
-  // this component needs and uses the detailsItemContext
-  const [detailsItem, dispatch] = useReducer(detailsReducer, {});
+//import { ResultItem } from "@/types/types";
 
-  //const resultParams = useSearchParams();
-  // const category = resultParams.get("category") as string;
-  // const searchText = resultParams.get("searchText") ?? undefined;
-  // const detailsText = resultParams.get("detailsText") ?? undefined;
+const DetailsComponent = () => {
+  const searchParams = useSearchParams();
+  const activeCategory = searchParams.get("category");
+  const searchText = searchParams.get("searchText") ?? undefined;
+  const detailsText = searchParams.get("detailsText") ?? undefined;
 
   return (
-    <DetailsItemContext.Provider value={detailsItem}>
-      <DetailsItemDispatchContext.Provider value={dispatch}>
-        <BackBar />
-        <DetailsItemCard />
-      </DetailsItemDispatchContext.Provider>
-    </DetailsItemContext.Provider>
+    <div className="flex flex-col md:px-10 lg:px-16 py-5 mb-8 bg-whitesmoke h-full">
+      <BackBar />
+      <DetailsItemCard />
+      <div>{activeCategory}</div>
+      <div>{searchText}</div>
+      <div>{detailsText}</div>
+    </div>
   );
 };
 
diff --git a/src/components/app/results/Details/DetailsItemCard.tsx b/src/components/app/results/Details/DetailsItemCard.tsx
index 99cd257..c5f4ca8 100644
--- a/src/components/app/results/Details/DetailsItemCard.tsx
+++ b/src/components/app/results/Details/DetailsItemCard.tsx
@@ -1,30 +1,30 @@
 "use client";
-import React, { useContext, useState, useEffect } from "react";
+import { useAtomValue } from "jotai";
+import React, { useState, useEffect } from "react";
 
-import { DetailsItemContext } from "@/context/detailsItem";
-import { ResultItem } from "@/types/types";
+import { detailsItemAtom } from "@/state/atoms";
+import { ResultItem as ResultItemType } from "@/types/types";
+
+import ResultItem from "../ListResults/ResultItem";
 
 const DetailsItemCard = () => {
-  const detailsItemFromReducer = useContext<ResultItem | object>(DetailsItemContext);
-  const [detailsItem, setDetailsItem] = useState<ResultItem | null>(null);
+  const detailsItemAtomValue: ResultItemType | undefined = useAtomValue(detailsItemAtom);
+  const [detailsItem, setDetailsItem] = useState<ResultItemType | undefined>();
 
   useEffect(() => {
-    console.log("In details card:", detailsItemFromReducer);
-    const isResultItem = (obj: object | ResultItem): obj is ResultItem =>
-      Object.keys(detailsItemFromReducer).length > 0;
+    const isResultItem = (
+      detailsItemAtomValue?: ResultItemType
+    ): detailsItemAtomValue is ResultItemType => detailsItemAtomValue !== undefined;
 
-    if (isResultItem(detailsItemFromReducer)) {
-      setDetailsItem(detailsItemFromReducer);
-    }
-  }, [detailsItemFromReducer]);
+    if (isResultItem(detailsItemAtomValue)) setDetailsItem(detailsItemAtomValue);
+  }, [detailsItemAtomValue]);
 
   return (
     <>
       {detailsItem ? (
-        <>
-          <div>{detailsItem.name}</div>
-          <div>{detailsItem.id}</div>
-        </>
+        <div className="p-4">
+          <ResultItem item={detailsItem} idx={detailsItem.id} inDetailsPage />
+        </div>
       ) : null}
     </>
   );
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index fa6ca19..6316785 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -1,17 +1,18 @@
 "use client";
 
+import { useSetAtom } from "jotai";
 import Image from "next/image";
 import { useRouter } from "next/navigation";
 import { useTranslations } from "next-intl";
-import { useEffect, useRef, useState, useReducer } from "react";
+import { useEffect, useRef, useState } from "react";
 
 import { INSTITUTE_ROR_LOGOS } from "@/app/api/config/config";
 import ExternalLink from "@/components/ExternalLink";
 import Relationships from "@/components/app/results/ListResults/ResultItem/Relationships";
-import { detailsReducer } from "@/context/detailsItem";
 import { Link } from "@/i18n";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
+import { detailsItemAtom } from "@/state/atoms";
 import type { Category, ResultItem as ResultItemType } from "@/types/types";
 
 type Props = {
@@ -19,12 +20,11 @@ type Props = {
   idx: string;
   searchText?: string;
   activeCategory?: Category;
+  inDetailsPage?: boolean;
 };
 
-const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
-  // create a item context
-  // const detailsItemContext =  createContext(item)
-  const [detailsItem, dispatch] = useReducer(detailsReducer, {});
+const ResultItem = ({ item, idx, searchText, activeCategory, inDetailsPage }: Props) => {
+  const setDetailsItem = useSetAtom(detailsItemAtom);
   const router = useRouter();
   const t = useTranslations("ResultItem");
   const s = useTranslations("BackendIds");
@@ -105,13 +105,8 @@ const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
     return filteredArr.length > 0 ? <Relationships filteredArr={filteredArr} type={type} /> : null;
   };
 
-  const handleOnClick = () => {
-    console.log("current detailsItem:", detailsItem);
-    // action object
-    dispatch({
-      type: "setDetailsRequested",
-      item,
-    });
+  const handleDetailSearch = () => {
+    setDetailsItem(() => item);
     router.push(
       `/results/details?category=${activeCategory?.id}${searchText ? `&searchText=${searchText}` : ``}&detailsText=${item.id}`
     );
@@ -123,8 +118,9 @@ const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
       className="my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white"
     >
       <button
-        className="inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau h-5 hover:transition-all hover:translate-x-3"
-        onClick={handleOnClick}
+        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau h-5`}
+        onClick={handleDetailSearch}
+        disabled={inDetailsPage}
       >
         {titleIconHref ? (
           <span className="mr-1">
@@ -140,7 +136,7 @@ const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
         <div className="font-semibold" rel="noreferrer">
           {item.name}
         </div>
-        <RightArrowIcon />
+        {inDetailsPage ?? <RightArrowIcon />}
       </button>
 
       <div className="text-sm">
@@ -252,7 +248,7 @@ const ResultItem = ({ item, idx, searchText, activeCategory }: Props) => {
           </p>
           {descShowReadMore ? (
             <button
-              className="py-0.75  float-right rounded-full border-[1px] border-secondary-helmholtz-mint px-2 text-xs hover:border-primary-helmholtz-hellblau"
+              className="py-0.75 float-right rounded-full border-[1px] border-secondary-helmholtz-mint px-2 text-xs hover:border-primary-helmholtz-hellblau"
               onClick={() => setDescShowMore(!descShowMore)}
             >
               {descShowMore ? t("show_less") : t("show_more")}
diff --git a/src/context/detailsItem.tsx b/src/context/detailsItem.tsx
deleted file mode 100644
index d769b22..0000000
--- a/src/context/detailsItem.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-"use client";
-
-import { createContext } from "react";
-
-import { ResultItem } from "@/types/types";
-
-export const detailsReducer = (
-  detailsItem: ResultItem | object,
-  action: { type: "setDetailsRequested" | "getDetailsRequested"; item?: ResultItem }
-) => {
-  switch (action.type) {
-    case "setDetailsRequested":
-      return { ...action.item };
-    case "getDetailsRequested":
-      return detailsItem !== null ? { ...detailsItem } : {};
-    default:
-      throw Error("Unknown action:", action.type);
-  }
-};
-
-export const DetailsItemContext = createContext<ResultItem | object>({});
-export const DetailsItemDispatchContext = createContext<ResultItem | object | null>(null);
diff --git a/src/state/atoms.tsx b/src/state/atoms.tsx
new file mode 100644
index 0000000..6aade35
--- /dev/null
+++ b/src/state/atoms.tsx
@@ -0,0 +1,5 @@
+import { atom } from "jotai";
+
+import { ResultItem } from "@/types/types";
+
+export const detailsItemAtom = atom<ResultItem>();
diff --git a/yarn.lock b/yarn.lock
index 0c14da5..00f1331 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6,9 +6,9 @@ __metadata:
   cacheKey: 10c0
 
 "@adobe/css-tools@npm:^4.4.0":
-  version: 4.4.0
-  resolution: "@adobe/css-tools@npm:4.4.0"
-  checksum: 10c0/d65ddc719389bf469097df80fb16a8af48a973dea4b57565789d70ac8e7ab4987e6dc0095da3ed5dc16c1b6f8960214a7590312eeda8abd543d91fd0f59e6c94
+  version: 4.4.1
+  resolution: "@adobe/css-tools@npm:4.4.1"
+  checksum: 10c0/1a68ad9af490f45fce7b6e50dd2d8ac0c546d74431649c0d42ee4ceb1a9fa057fae0a7ef1e148effa12d84ec00ed71869ebfe0fb1dcdcc80bfcb6048c12abcc0
   languageName: node
   linkType: hard
 
@@ -29,163 +29,142 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.24.7":
-  version: 7.24.7
-  resolution: "@babel/code-frame@npm:7.24.7"
+"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2":
+  version: 7.26.2
+  resolution: "@babel/code-frame@npm:7.26.2"
   dependencies:
-    "@babel/highlight": "npm:^7.24.7"
+    "@babel/helper-validator-identifier": "npm:^7.25.9"
+    js-tokens: "npm:^4.0.0"
     picocolors: "npm:^1.0.0"
-  checksum: 10c0/ab0af539473a9f5aeaac7047e377cb4f4edd255a81d84a76058595f8540784cc3fbe8acf73f1e073981104562490aabfb23008cd66dc677a456a4ed5390fdde6
+  checksum: 10c0/7d79621a6849183c415486af99b1a20b84737e8c11cd55b6544f688c51ce1fd710e6d869c3dd21232023da272a79b91efb3e83b5bc2dc65c1187c5fcd1b72ea8
   languageName: node
   linkType: hard
 
-"@babel/compat-data@npm:^7.25.2":
-  version: 7.25.4
-  resolution: "@babel/compat-data@npm:7.25.4"
-  checksum: 10c0/50d79734d584a28c69d6f5b99adfaa064d0f41609a378aef04eb06accc5b44f8520e68549eba3a082478180957b7d5783f1bfb1672e4ae8574e797ce8bae79fa
+"@babel/compat-data@npm:^7.25.9":
+  version: 7.26.3
+  resolution: "@babel/compat-data@npm:7.26.3"
+  checksum: 10c0/d63e71845c34dfad8d7ff8c15b562e620dbf60e68e3abfa35681d24d612594e8e5ec9790d831a287ecd79ce00f48e7ffddc85c5ce94af7242d45917b9c1a5f90
   languageName: node
   linkType: hard
 
 "@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9":
-  version: 7.25.2
-  resolution: "@babel/core@npm:7.25.2"
+  version: 7.26.0
+  resolution: "@babel/core@npm:7.26.0"
   dependencies:
     "@ampproject/remapping": "npm:^2.2.0"
-    "@babel/code-frame": "npm:^7.24.7"
-    "@babel/generator": "npm:^7.25.0"
-    "@babel/helper-compilation-targets": "npm:^7.25.2"
-    "@babel/helper-module-transforms": "npm:^7.25.2"
-    "@babel/helpers": "npm:^7.25.0"
-    "@babel/parser": "npm:^7.25.0"
-    "@babel/template": "npm:^7.25.0"
-    "@babel/traverse": "npm:^7.25.2"
-    "@babel/types": "npm:^7.25.2"
+    "@babel/code-frame": "npm:^7.26.0"
+    "@babel/generator": "npm:^7.26.0"
+    "@babel/helper-compilation-targets": "npm:^7.25.9"
+    "@babel/helper-module-transforms": "npm:^7.26.0"
+    "@babel/helpers": "npm:^7.26.0"
+    "@babel/parser": "npm:^7.26.0"
+    "@babel/template": "npm:^7.25.9"
+    "@babel/traverse": "npm:^7.25.9"
+    "@babel/types": "npm:^7.26.0"
     convert-source-map: "npm:^2.0.0"
     debug: "npm:^4.1.0"
     gensync: "npm:^1.0.0-beta.2"
     json5: "npm:^2.2.3"
     semver: "npm:^6.3.1"
-  checksum: 10c0/a425fa40e73cb72b6464063a57c478bc2de9dbcc19c280f1b55a3d88b35d572e87e8594e7d7b4880331addb6faef641bbeb701b91b41b8806cd4deae5d74f401
+  checksum: 10c0/91de73a7ff5c4049fbc747930aa039300e4d2670c2a91f5aa622f1b4868600fc89b01b6278385fbcd46f9574186fa3d9b376a9e7538e50f8d118ec13cfbcb63e
   languageName: node
   linkType: hard
 
-"@babel/generator@npm:^7.25.0, @babel/generator@npm:^7.25.6, @babel/generator@npm:^7.7.2":
-  version: 7.25.6
-  resolution: "@babel/generator@npm:7.25.6"
+"@babel/generator@npm:^7.26.0, @babel/generator@npm:^7.26.3, @babel/generator@npm:^7.7.2":
+  version: 7.26.3
+  resolution: "@babel/generator@npm:7.26.3"
   dependencies:
-    "@babel/types": "npm:^7.25.6"
+    "@babel/parser": "npm:^7.26.3"
+    "@babel/types": "npm:^7.26.3"
     "@jridgewell/gen-mapping": "npm:^0.3.5"
     "@jridgewell/trace-mapping": "npm:^0.3.25"
-    jsesc: "npm:^2.5.1"
-  checksum: 10c0/f89282cce4ddc63654470b98086994d219407d025497f483eb03ba102086e11e2b685b27122f6ff2e1d93b5b5fa0c3a6b7e974fbf2e4a75b685041a746a4291e
+    jsesc: "npm:^3.0.2"
+  checksum: 10c0/54f260558e3e4ec8942da3cde607c35349bb983c3a7c5121243f96893fba3e8cd62e1f1773b2051f936f8c8a10987b758d5c7d76dbf2784e95bb63ab4843fa00
   languageName: node
   linkType: hard
 
-"@babel/helper-compilation-targets@npm:^7.25.2":
-  version: 7.25.2
-  resolution: "@babel/helper-compilation-targets@npm:7.25.2"
+"@babel/helper-compilation-targets@npm:^7.25.9":
+  version: 7.25.9
+  resolution: "@babel/helper-compilation-targets@npm:7.25.9"
   dependencies:
-    "@babel/compat-data": "npm:^7.25.2"
-    "@babel/helper-validator-option": "npm:^7.24.8"
-    browserslist: "npm:^4.23.1"
+    "@babel/compat-data": "npm:^7.25.9"
+    "@babel/helper-validator-option": "npm:^7.25.9"
+    browserslist: "npm:^4.24.0"
     lru-cache: "npm:^5.1.1"
     semver: "npm:^6.3.1"
-  checksum: 10c0/de10e986b5322c9f807350467dc845ec59df9e596a5926a3b5edbb4710d8e3b8009d4396690e70b88c3844fe8ec4042d61436dd4b92d1f5f75655cf43ab07e99
+  checksum: 10c0/a6b26a1e4222e69ef8e62ee19374308f060b007828bc11c65025ecc9e814aba21ff2175d6d3f8bf53c863edd728ee8f94ba7870f8f90a37d39552ad9933a8aaa
   languageName: node
   linkType: hard
 
-"@babel/helper-module-imports@npm:^7.24.7":
-  version: 7.24.7
-  resolution: "@babel/helper-module-imports@npm:7.24.7"
+"@babel/helper-module-imports@npm:^7.25.9":
+  version: 7.25.9
+  resolution: "@babel/helper-module-imports@npm:7.25.9"
   dependencies:
-    "@babel/traverse": "npm:^7.24.7"
-    "@babel/types": "npm:^7.24.7"
-  checksum: 10c0/97c57db6c3eeaea31564286e328a9fb52b0313c5cfcc7eee4bc226aebcf0418ea5b6fe78673c0e4a774512ec6c86e309d0f326e99d2b37bfc16a25a032498af0
+    "@babel/traverse": "npm:^7.25.9"
+    "@babel/types": "npm:^7.25.9"
+  checksum: 10c0/078d3c2b45d1f97ffe6bb47f61961be4785d2342a4156d8b42c92ee4e1b7b9e365655dd6cb25329e8fe1a675c91eeac7e3d04f0c518b67e417e29d6e27b6aa70
   languageName: node
   linkType: hard
 
-"@babel/helper-module-transforms@npm:^7.25.2":
-  version: 7.25.2
-  resolution: "@babel/helper-module-transforms@npm:7.25.2"
+"@babel/helper-module-transforms@npm:^7.26.0":
+  version: 7.26.0
+  resolution: "@babel/helper-module-transforms@npm:7.26.0"
   dependencies:
-    "@babel/helper-module-imports": "npm:^7.24.7"
-    "@babel/helper-simple-access": "npm:^7.24.7"
-    "@babel/helper-validator-identifier": "npm:^7.24.7"
-    "@babel/traverse": "npm:^7.25.2"
+    "@babel/helper-module-imports": "npm:^7.25.9"
+    "@babel/helper-validator-identifier": "npm:^7.25.9"
+    "@babel/traverse": "npm:^7.25.9"
   peerDependencies:
     "@babel/core": ^7.0.0
-  checksum: 10c0/adaa15970ace0aee5934b5a633789b5795b6229c6a9cf3e09a7e80aa33e478675eee807006a862aa9aa517935d81f88a6db8a9f5936e3a2a40ec75f8062bc329
+  checksum: 10c0/ee111b68a5933481d76633dad9cdab30c41df4479f0e5e1cc4756dc9447c1afd2c9473b5ba006362e35b17f4ebddd5fca090233bef8dfc84dca9d9127e56ec3a
   languageName: node
   linkType: hard
 
-"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0":
-  version: 7.24.8
-  resolution: "@babel/helper-plugin-utils@npm:7.24.8"
-  checksum: 10c0/0376037f94a3bfe6b820a39f81220ac04f243eaee7193774b983e956c1750883ff236b30785795abbcda43fac3ece74750566830c2daa4d6e3870bb0dff34c2d
-  languageName: node
-  linkType: hard
-
-"@babel/helper-simple-access@npm:^7.24.7":
-  version: 7.24.7
-  resolution: "@babel/helper-simple-access@npm:7.24.7"
-  dependencies:
-    "@babel/traverse": "npm:^7.24.7"
-    "@babel/types": "npm:^7.24.7"
-  checksum: 10c0/7230e419d59a85f93153415100a5faff23c133d7442c19e0cd070da1784d13cd29096ee6c5a5761065c44e8164f9f80e3a518c41a0256df39e38f7ad6744fed7
+"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.25.9, @babel/helper-plugin-utils@npm:^7.8.0":
+  version: 7.25.9
+  resolution: "@babel/helper-plugin-utils@npm:7.25.9"
+  checksum: 10c0/483066a1ba36ff16c0116cd24f93de05de746a603a777cd695ac7a1b034928a65a4ecb35f255761ca56626435d7abdb73219eba196f9aa83b6c3c3169325599d
   languageName: node
   linkType: hard
 
-"@babel/helper-string-parser@npm:^7.24.8":
-  version: 7.24.8
-  resolution: "@babel/helper-string-parser@npm:7.24.8"
-  checksum: 10c0/6361f72076c17fabf305e252bf6d580106429014b3ab3c1f5c4eb3e6d465536ea6b670cc0e9a637a77a9ad40454d3e41361a2909e70e305116a23d68ce094c08
+"@babel/helper-string-parser@npm:^7.25.9":
+  version: 7.25.9
+  resolution: "@babel/helper-string-parser@npm:7.25.9"
+  checksum: 10c0/7244b45d8e65f6b4338a6a68a8556f2cb161b782343e97281a5f2b9b93e420cad0d9f5773a59d79f61d0c448913d06f6a2358a87f2e203cf112e3c5b53522ee6
   languageName: node
   linkType: hard
 
-"@babel/helper-validator-identifier@npm:^7.24.7":
-  version: 7.24.7
-  resolution: "@babel/helper-validator-identifier@npm:7.24.7"
-  checksum: 10c0/87ad608694c9477814093ed5b5c080c2e06d44cb1924ae8320474a74415241223cc2a725eea2640dd783ff1e3390e5f95eede978bc540e870053152e58f1d651
+"@babel/helper-validator-identifier@npm:^7.25.9":
+  version: 7.25.9
+  resolution: "@babel/helper-validator-identifier@npm:7.25.9"
+  checksum: 10c0/4fc6f830177b7b7e887ad3277ddb3b91d81e6c4a24151540d9d1023e8dc6b1c0505f0f0628ae653601eb4388a8db45c1c14b2c07a9173837aef7e4116456259d
   languageName: node
   linkType: hard
 
-"@babel/helper-validator-option@npm:^7.24.8":
-  version: 7.24.8
-  resolution: "@babel/helper-validator-option@npm:7.24.8"
-  checksum: 10c0/73db93a34ae89201351288bee7623eed81a54000779462a986105b54ffe82069e764afd15171a428b82e7c7a9b5fec10b5d5603b216317a414062edf5c67a21f
+"@babel/helper-validator-option@npm:^7.25.9":
+  version: 7.25.9
+  resolution: "@babel/helper-validator-option@npm:7.25.9"
+  checksum: 10c0/27fb195d14c7dcb07f14e58fe77c44eea19a6a40a74472ec05c441478fa0bb49fa1c32b2d64be7a38870ee48ef6601bdebe98d512f0253aea0b39756c4014f3e
   languageName: node
   linkType: hard
 
-"@babel/helpers@npm:^7.25.0":
-  version: 7.25.6
-  resolution: "@babel/helpers@npm:7.25.6"
+"@babel/helpers@npm:^7.26.0":
+  version: 7.26.0
+  resolution: "@babel/helpers@npm:7.26.0"
   dependencies:
-    "@babel/template": "npm:^7.25.0"
-    "@babel/types": "npm:^7.25.6"
-  checksum: 10c0/448c1cdabccca42fd97a252f73f1e4bcd93776dbf24044f3b4f49b756bf2ece73ee6df05177473bb74ea7456dddd18d6f481e4d96d2cc7839d078900d48c696c
-  languageName: node
-  linkType: hard
-
-"@babel/highlight@npm:^7.24.7":
-  version: 7.24.7
-  resolution: "@babel/highlight@npm:7.24.7"
-  dependencies:
-    "@babel/helper-validator-identifier": "npm:^7.24.7"
-    chalk: "npm:^2.4.2"
-    js-tokens: "npm:^4.0.0"
-    picocolors: "npm:^1.0.0"
-  checksum: 10c0/674334c571d2bb9d1c89bdd87566383f59231e16bcdcf5bb7835babdf03c9ae585ca0887a7b25bdf78f303984af028df52831c7989fecebb5101cc132da9393a
+    "@babel/template": "npm:^7.25.9"
+    "@babel/types": "npm:^7.26.0"
+  checksum: 10c0/343333cced6946fe46617690a1d0789346960910225ce359021a88a60a65bc0d791f0c5d240c0ed46cf8cc63b5fd7df52734ff14e43b9c32feae2b61b1647097
   languageName: node
   linkType: hard
 
-"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.0, @babel/parser@npm:^7.25.6":
-  version: 7.25.6
-  resolution: "@babel/parser@npm:7.25.6"
+"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.3":
+  version: 7.26.3
+  resolution: "@babel/parser@npm:7.26.3"
   dependencies:
-    "@babel/types": "npm:^7.25.6"
+    "@babel/types": "npm:^7.26.3"
   bin:
     parser: ./bin/babel-parser.js
-  checksum: 10c0/f88a0e895dbb096fd37c4527ea97d12b5fc013720602580a941ac3a339698872f0c911e318c292b184c36b5fbe23b612f05aff9d24071bc847c7b1c21552c41d
+  checksum: 10c0/48f736374e61cfd10ddbf7b80678514ae1f16d0e88bc793d2b505d73d9b987ea786fc8c2f7ee8f8b8c467df062030eb07fd0eb2168f0f541ca1f542775852cad
   languageName: node
   linkType: hard
 
@@ -234,13 +213,13 @@ __metadata:
   linkType: hard
 
 "@babel/plugin-syntax-import-attributes@npm:^7.24.7":
-  version: 7.25.6
-  resolution: "@babel/plugin-syntax-import-attributes@npm:7.25.6"
+  version: 7.26.0
+  resolution: "@babel/plugin-syntax-import-attributes@npm:7.26.0"
   dependencies:
-    "@babel/helper-plugin-utils": "npm:^7.24.8"
+    "@babel/helper-plugin-utils": "npm:^7.25.9"
   peerDependencies:
     "@babel/core": ^7.0.0-0
-  checksum: 10c0/0e9359cf2d117476310961dfcfd7204ed692e933707da10d6194153d3996cd2ea5b7635fc90d720dce3612083af89966bb862561064a509c350320dc98644751
+  checksum: 10c0/e594c185b12bfe0bbe7ca78dfeebe870e6d569a12128cac86f3164a075fe0ff70e25ddbd97fd0782906b91f65560c9dc6957716b7b4a68aba2516c9b7455e352
   languageName: node
   linkType: hard
 
@@ -267,13 +246,13 @@ __metadata:
   linkType: hard
 
 "@babel/plugin-syntax-jsx@npm:^7.7.2":
-  version: 7.24.7
-  resolution: "@babel/plugin-syntax-jsx@npm:7.24.7"
+  version: 7.25.9
+  resolution: "@babel/plugin-syntax-jsx@npm:7.25.9"
   dependencies:
-    "@babel/helper-plugin-utils": "npm:^7.24.7"
+    "@babel/helper-plugin-utils": "npm:^7.25.9"
   peerDependencies:
     "@babel/core": ^7.0.0-0
-  checksum: 10c0/f44d927a9ae8d5ef016ff5b450e1671e56629ddc12e56b938e41fd46e141170d9dfc9a53d6cb2b9a20a7dd266a938885e6a3981c60c052a2e1daed602ac80e51
+  checksum: 10c0/d56597aff4df39d3decda50193b6dfbe596ca53f437ff2934622ce19a743bf7f43492d3fb3308b0289f5cee2b825d99ceb56526a2b9e7b68bf04901546c5618c
   languageName: node
   linkType: hard
 
@@ -366,59 +345,58 @@ __metadata:
   linkType: hard
 
 "@babel/plugin-syntax-typescript@npm:^7.7.2":
-  version: 7.25.4
-  resolution: "@babel/plugin-syntax-typescript@npm:7.25.4"
+  version: 7.25.9
+  resolution: "@babel/plugin-syntax-typescript@npm:7.25.9"
   dependencies:
-    "@babel/helper-plugin-utils": "npm:^7.24.8"
+    "@babel/helper-plugin-utils": "npm:^7.25.9"
   peerDependencies:
     "@babel/core": ^7.0.0-0
-  checksum: 10c0/199919d44c73e5edee9ffd311cf638f88d26a810189e32d338c46c7600441fd5c4a2e431f9be377707cbf318410895304e90b83bf8d9011d205150fa7f260e63
+  checksum: 10c0/5192ebe11bd46aea68b7a60fd9555465c59af7e279e71126788e59121b86e00b505816685ab4782abe159232b0f73854e804b54449820b0d950b397ee158caa2
   languageName: node
   linkType: hard
 
 "@babel/runtime@npm:^7.12.5":
-  version: 7.25.6
-  resolution: "@babel/runtime@npm:7.25.6"
+  version: 7.26.0
+  resolution: "@babel/runtime@npm:7.26.0"
   dependencies:
     regenerator-runtime: "npm:^0.14.0"
-  checksum: 10c0/d6143adf5aa1ce79ed374e33fdfd74fa975055a80bc6e479672ab1eadc4e4bfd7484444e17dd063a1d180e051f3ec62b357c7a2b817e7657687b47313158c3d2
+  checksum: 10c0/12c01357e0345f89f4f7e8c0e81921f2a3e3e101f06e8eaa18a382b517376520cd2fa8c237726eb094dab25532855df28a7baaf1c26342b52782f6936b07c287
   languageName: node
   linkType: hard
 
-"@babel/template@npm:^7.25.0, @babel/template@npm:^7.3.3":
-  version: 7.25.0
-  resolution: "@babel/template@npm:7.25.0"
+"@babel/template@npm:^7.25.9, @babel/template@npm:^7.3.3":
+  version: 7.25.9
+  resolution: "@babel/template@npm:7.25.9"
   dependencies:
-    "@babel/code-frame": "npm:^7.24.7"
-    "@babel/parser": "npm:^7.25.0"
-    "@babel/types": "npm:^7.25.0"
-  checksum: 10c0/4e31afd873215744c016e02b04f43b9fa23205d6d0766fb2e93eb4091c60c1b88897936adb895fb04e3c23de98dfdcbe31bc98daaa1a4e0133f78bb948e1209b
+    "@babel/code-frame": "npm:^7.25.9"
+    "@babel/parser": "npm:^7.25.9"
+    "@babel/types": "npm:^7.25.9"
+  checksum: 10c0/ebe677273f96a36c92cc15b7aa7b11cc8bc8a3bb7a01d55b2125baca8f19cae94ff3ce15f1b1880fb8437f3a690d9f89d4e91f16fc1dc4d3eb66226d128983ab
   languageName: node
   linkType: hard
 
-"@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.25.2":
-  version: 7.25.6
-  resolution: "@babel/traverse@npm:7.25.6"
+"@babel/traverse@npm:^7.25.9":
+  version: 7.26.4
+  resolution: "@babel/traverse@npm:7.26.4"
   dependencies:
-    "@babel/code-frame": "npm:^7.24.7"
-    "@babel/generator": "npm:^7.25.6"
-    "@babel/parser": "npm:^7.25.6"
-    "@babel/template": "npm:^7.25.0"
-    "@babel/types": "npm:^7.25.6"
+    "@babel/code-frame": "npm:^7.26.2"
+    "@babel/generator": "npm:^7.26.3"
+    "@babel/parser": "npm:^7.26.3"
+    "@babel/template": "npm:^7.25.9"
+    "@babel/types": "npm:^7.26.3"
     debug: "npm:^4.3.1"
     globals: "npm:^11.1.0"
-  checksum: 10c0/964304c6fa46bd705428ba380bf73177eeb481c3f26d82ea3d0661242b59e0dd4329d23886035e9ca9a4ceb565c03a76fd615109830687a27bcd350059d6377e
+  checksum: 10c0/cf25d0eda9505daa0f0832ad786b9e28c9d967e823aaf7fbe425250ab198c656085495aa6bed678b27929e095c84eea9fd778b851a31803da94c9bc4bf4eaef7
   languageName: node
   linkType: hard
 
-"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.2, @babel/types@npm:^7.25.6, @babel/types@npm:^7.3.3":
-  version: 7.25.6
-  resolution: "@babel/types@npm:7.25.6"
+"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.26.3, @babel/types@npm:^7.3.3":
+  version: 7.26.3
+  resolution: "@babel/types@npm:7.26.3"
   dependencies:
-    "@babel/helper-string-parser": "npm:^7.24.8"
-    "@babel/helper-validator-identifier": "npm:^7.24.7"
-    to-fast-properties: "npm:^2.0.0"
-  checksum: 10c0/89d45fbee24e27a05dca2d08300a26b905bd384a480448823f6723c72d3a30327c517476389b7280ce8cb9a2c48ef8f47da7f9f6d326faf6f53fd6b68237bdc4
+    "@babel/helper-string-parser": "npm:^7.25.9"
+    "@babel/helper-validator-identifier": "npm:^7.25.9"
+  checksum: 10c0/966c5242c5e55c8704bf7a7418e7be2703a0afa4d19a8480999d5a4ef13d095dd60686615fe5983cb7593b4b06ba3a7de8d6ca501c1d78bdd233a10d90be787b
   languageName: node
   linkType: hard
 
@@ -439,29 +417,29 @@ __metadata:
   linkType: hard
 
 "@emnapi/runtime@npm:^1.2.0":
-  version: 1.2.0
-  resolution: "@emnapi/runtime@npm:1.2.0"
+  version: 1.3.1
+  resolution: "@emnapi/runtime@npm:1.3.1"
   dependencies:
     tslib: "npm:^2.4.0"
-  checksum: 10c0/7005ff8b67724c9e61b6cd79a3decbdb2ce25d24abd4d3d187472f200ee6e573329c30264335125fb136bd813aa9cf9f4f7c9391d04b07dd1e63ce0a3427be57
+  checksum: 10c0/060ffede50f1b619c15083312b80a9e62a5b0c87aa8c1b54854c49766c9d69f8d1d3d87bd963a647071263a320db41b25eaa50b74d6a80dcc763c23dbeaafd6c
   languageName: node
   linkType: hard
 
 "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0":
-  version: 4.4.0
-  resolution: "@eslint-community/eslint-utils@npm:4.4.0"
+  version: 4.4.1
+  resolution: "@eslint-community/eslint-utils@npm:4.4.1"
   dependencies:
-    eslint-visitor-keys: "npm:^3.3.0"
+    eslint-visitor-keys: "npm:^3.4.3"
   peerDependencies:
     eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
-  checksum: 10c0/7e559c4ce59cd3a06b1b5a517b593912e680a7f981ae7affab0d01d709e99cd5647019be8fafa38c350305bc32f1f7d42c7073edde2ab536c745e365f37b607e
+  checksum: 10c0/2aa0ac2fc50ff3f234408b10900ed4f1a0b19352f21346ad4cc3d83a1271481bdda11097baa45d484dd564c895e0762a27a8240be7a256b3ad47129e96528252
   languageName: node
   linkType: hard
 
 "@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1":
-  version: 4.11.1
-  resolution: "@eslint-community/regexpp@npm:4.11.1"
-  checksum: 10c0/fbcc1cb65ef5ed5b92faa8dc542e035269065e7ebcc0b39c81a4fe98ad35cfff20b3c8df048641de15a7757e07d69f85e2579c1a5055f993413ba18c055654f8
+  version: 4.12.1
+  resolution: "@eslint-community/regexpp@npm:4.12.1"
+  checksum: 10c0/a03d98c246bcb9109aec2c08e4d10c8d010256538dcb3f56610191607214523d4fb1b00aa81df830b6dffb74c5fa0be03642513a289c567949d3e550ca11cdf6
   languageName: node
   linkType: hard
 
@@ -499,7 +477,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@formatjs/fast-memoize@npm:2.2.0, @formatjs/fast-memoize@npm:^2.2.0":
+"@formatjs/fast-memoize@npm:2.2.0":
   version: 2.2.0
   resolution: "@formatjs/fast-memoize@npm:2.2.0"
   dependencies:
@@ -508,6 +486,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@formatjs/fast-memoize@npm:^2.2.0":
+  version: 2.2.5
+  resolution: "@formatjs/fast-memoize@npm:2.2.5"
+  dependencies:
+    tslib: "npm:2"
+  checksum: 10c0/3a2b930d8d866d9e8a008b974f859875b2c920a1a5c472090658bed132a1e1a3c9ba68ce460e87a7bc15caea95e514e84c75c0bc3735f9422ede2b1b5aef9e76
+  languageName: node
+  linkType: hard
+
 "@formatjs/icu-messageformat-parser@npm:2.7.8":
   version: 2.7.8
   resolution: "@formatjs/icu-messageformat-parser@npm:2.7.8"
@@ -774,6 +761,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@isaacs/fs-minipass@npm:^4.0.0":
+  version: 4.0.1
+  resolution: "@isaacs/fs-minipass@npm:4.0.1"
+  dependencies:
+    minipass: "npm:^7.0.4"
+  checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2
+  languageName: node
+  linkType: hard
+
 "@istanbuljs/load-nyc-config@npm:^1.0.0":
   version: 1.1.0
   resolution: "@istanbuljs/load-nyc-config@npm:1.1.0"
@@ -1025,13 +1021,13 @@ __metadata:
   linkType: hard
 
 "@jridgewell/gen-mapping@npm:^0.3.2, @jridgewell/gen-mapping@npm:^0.3.5":
-  version: 0.3.5
-  resolution: "@jridgewell/gen-mapping@npm:0.3.5"
+  version: 0.3.8
+  resolution: "@jridgewell/gen-mapping@npm:0.3.8"
   dependencies:
     "@jridgewell/set-array": "npm:^1.2.1"
     "@jridgewell/sourcemap-codec": "npm:^1.4.10"
     "@jridgewell/trace-mapping": "npm:^0.3.24"
-  checksum: 10c0/1be4fd4a6b0f41337c4f5fdf4afc3bd19e39c3691924817108b82ffcb9c9e609c273f936932b9fba4b3a298ce2eb06d9bff4eb1cc3bd81c4f4ee1b4917e25feb
+  checksum: 10c0/c668feaf86c501d7c804904a61c23c67447b2137b813b9ce03eca82cb9d65ac7006d766c218685d76e3d72828279b6ee26c347aa1119dab23fbaf36aed51585a
   languageName: node
   linkType: hard
 
@@ -1189,25 +1185,25 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@npmcli/agent@npm:^2.0.0":
-  version: 2.2.2
-  resolution: "@npmcli/agent@npm:2.2.2"
+"@npmcli/agent@npm:^3.0.0":
+  version: 3.0.0
+  resolution: "@npmcli/agent@npm:3.0.0"
   dependencies:
     agent-base: "npm:^7.1.0"
     http-proxy-agent: "npm:^7.0.0"
     https-proxy-agent: "npm:^7.0.1"
     lru-cache: "npm:^10.0.1"
     socks-proxy-agent: "npm:^8.0.3"
-  checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae
+  checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271
   languageName: node
   linkType: hard
 
-"@npmcli/fs@npm:^3.1.0":
-  version: 3.1.1
-  resolution: "@npmcli/fs@npm:3.1.1"
+"@npmcli/fs@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "@npmcli/fs@npm:4.0.0"
   dependencies:
     semver: "npm:^7.3.5"
-  checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99
+  checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5
   languageName: node
   linkType: hard
 
@@ -1274,21 +1270,21 @@ __metadata:
   linkType: hard
 
 "@tanstack/react-virtual@npm:^3.0.0-beta.60":
-  version: 3.10.8
-  resolution: "@tanstack/react-virtual@npm:3.10.8"
+  version: 3.11.1
+  resolution: "@tanstack/react-virtual@npm:3.11.1"
   dependencies:
-    "@tanstack/virtual-core": "npm:3.10.8"
+    "@tanstack/virtual-core": "npm:3.10.9"
   peerDependencies:
-    react: ^16.8.0 || ^17.0.0 || ^18.0.0
-    react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
-  checksum: 10c0/b7aec88ef48f604d3e7245b9996ba42f06e6ee2c1a45146cb96814cb3873a4c888bf86d26d10284c847a5ed97e16dc9430c380387abc1231c2e43c00f6ebadff
+    react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+    react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+  checksum: 10c0/5eafab335de0c65daa8ad8fe732c506bea922861032aad35732ca65ff16fdbb111bd4e72fafc0d3f4449a793ceba4ed0fcadb27390bda6f5c8ba4a55737d556d
   languageName: node
   linkType: hard
 
-"@tanstack/virtual-core@npm:3.10.8":
-  version: 3.10.8
-  resolution: "@tanstack/virtual-core@npm:3.10.8"
-  checksum: 10c0/ddb97cd03d84b343b38a2c14d85e33c788f4af622fccc0fdf997caf4e83e47e8f67b099b854c7dc4337d7662f647625ab3247cd8aa1bc9d4dda701bda83245f6
+"@tanstack/virtual-core@npm:3.10.9":
+  version: 3.10.9
+  resolution: "@tanstack/virtual-core@npm:3.10.9"
+  checksum: 10c0/960cde330235daff5403e0da23837ac30a0f95a02c8866692f8382d03b675d6802e129436b0b3e7e737d8a5347ef2cadec448ba4c0878462228c094440d0207b
   languageName: node
   linkType: hard
 
@@ -1309,8 +1305,8 @@ __metadata:
   linkType: hard
 
 "@testing-library/jest-dom@npm:^6.4.2":
-  version: 6.5.0
-  resolution: "@testing-library/jest-dom@npm:6.5.0"
+  version: 6.6.3
+  resolution: "@testing-library/jest-dom@npm:6.6.3"
   dependencies:
     "@adobe/css-tools": "npm:^4.4.0"
     aria-query: "npm:^5.0.0"
@@ -1319,7 +1315,7 @@ __metadata:
     dom-accessibility-api: "npm:^0.6.3"
     lodash: "npm:^4.17.21"
     redent: "npm:^3.0.0"
-  checksum: 10c0/fd5936a547f04608d8de15a7de3ae26516f21023f8f45169b10c8c8847015fd20ec259b7309f08aa1031bcbc37c6e5e6f532d1bb85ef8f91bad654193ec66a4c
+  checksum: 10c0/5566b6c0b7b0709bc244aec3aa3dc9e5f4663e8fb2b99d8cd456fc07279e59db6076cbf798f9d3099a98fca7ef4cd50e4e1f4c4dec5a60a8fad8d24a638a5bf6
   languageName: node
   linkType: hard
 
@@ -1420,49 +1416,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/body-parser@npm:*":
-  version: 1.19.5
-  resolution: "@types/body-parser@npm:1.19.5"
-  dependencies:
-    "@types/connect": "npm:*"
-    "@types/node": "npm:*"
-  checksum: 10c0/aebeb200f25e8818d8cf39cd0209026750d77c9b85381cdd8deeb50913e4d18a1ebe4b74ca9b0b4d21952511eeaba5e9fbbf739b52731a2061e206ec60d568df
-  languageName: node
-  linkType: hard
-
-"@types/connect@npm:*":
-  version: 3.4.38
-  resolution: "@types/connect@npm:3.4.38"
-  dependencies:
-    "@types/node": "npm:*"
-  checksum: 10c0/2e1cdba2c410f25649e77856505cd60223250fa12dff7a503e492208dbfdd25f62859918f28aba95315251fd1f5e1ffbfca1e25e73037189ab85dd3f8d0a148c
-  languageName: node
-  linkType: hard
-
-"@types/express-serve-static-core@npm:^4.17.33":
-  version: 4.19.5
-  resolution: "@types/express-serve-static-core@npm:4.19.5"
-  dependencies:
-    "@types/node": "npm:*"
-    "@types/qs": "npm:*"
-    "@types/range-parser": "npm:*"
-    "@types/send": "npm:*"
-  checksum: 10c0/ba8d8d976ab797b2602c60e728802ff0c98a00f13d420d82770f3661b67fa36ea9d3be0b94f2ddd632afe1fbc6e41620008b01db7e4fabdd71a2beb5539b0725
-  languageName: node
-  linkType: hard
-
-"@types/express@npm:^4.17.21":
-  version: 4.17.21
-  resolution: "@types/express@npm:4.17.21"
-  dependencies:
-    "@types/body-parser": "npm:*"
-    "@types/express-serve-static-core": "npm:^4.17.33"
-    "@types/qs": "npm:*"
-    "@types/serve-static": "npm:*"
-  checksum: 10c0/12e562c4571da50c7d239e117e688dc434db1bac8be55613294762f84fd77fbd0658ccd553c7d3ab02408f385bc93980992369dd30e2ecd2c68c358e6af8fabf
-  languageName: node
-  linkType: hard
-
 "@types/graceful-fs@npm:^4.1.3":
   version: 4.1.9
   resolution: "@types/graceful-fs@npm:4.1.9"
@@ -1472,13 +1425,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/http-errors@npm:*":
-  version: 2.0.4
-  resolution: "@types/http-errors@npm:2.0.4"
-  checksum: 10c0/494670a57ad4062fee6c575047ad5782506dd35a6b9ed3894cea65830a94367bd84ba302eb3dde331871f6d70ca287bfedb1b2cf658e6132cd2cbd427ab56836
-  languageName: node
-  linkType: hard
-
 "@types/isomorphic-fetch@npm:^0.0.39":
   version: 0.0.39
   resolution: "@types/isomorphic-fetch@npm:0.0.39"
@@ -1512,12 +1458,12 @@ __metadata:
   linkType: hard
 
 "@types/jest@npm:^29.5.12":
-  version: 29.5.13
-  resolution: "@types/jest@npm:29.5.13"
+  version: 29.5.14
+  resolution: "@types/jest@npm:29.5.14"
   dependencies:
     expect: "npm:^29.0.0"
     pretty-format: "npm:^29.0.0"
-  checksum: 10c0/9c31af0b155387b9860908830de63c6b79011d7c87c8b61b39da124e26e55423dd51b006749aafe4f0ef3a065016619a1f93ef4b055157d43727f448e67824b7
+  checksum: 10c0/18e0712d818890db8a8dab3d91e9ea9f7f19e3f83c2e50b312f557017dc81466207a71f3ed79cf4428e813ba939954fa26ffa0a9a7f153181ba174581b1c2aed
   languageName: node
   linkType: hard
 
@@ -1546,68 +1492,38 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/mime@npm:^1":
-  version: 1.3.5
-  resolution: "@types/mime@npm:1.3.5"
-  checksum: 10c0/c2ee31cd9b993804df33a694d5aa3fa536511a49f2e06eeab0b484fef59b4483777dbb9e42a4198a0809ffbf698081fdbca1e5c2218b82b91603dfab10a10fbc
-  languageName: node
-  linkType: hard
-
-"@types/node@npm:*":
-  version: 22.5.5
-  resolution: "@types/node@npm:22.5.5"
+"@types/node@npm:*, @types/node@npm:^20":
+  version: 20.17.5
+  resolution: "@types/node@npm:20.17.5"
   dependencies:
     undici-types: "npm:~6.19.2"
-  checksum: 10c0/ead9495cfc6b1da5e7025856dcce2591e9bae635357410c0d2dd619fce797d2a1d402887580ca4b336cb78168b195224869967de370a23f61663cf1e4836121c
-  languageName: node
-  linkType: hard
-
-"@types/node@npm:^20":
-  version: 20.16.5
-  resolution: "@types/node@npm:20.16.5"
-  dependencies:
-    undici-types: "npm:~6.19.2"
-  checksum: 10c0/6af7994129815010bcbc4cf8221865559c8116ff43e74a6549525c2108267596fc2d18aff5d5ecfe089fb60a119f975631343e2c65c52bfa0955ed9dc56733d6
+  checksum: 10c0/6e6bf7f84365a2ee95a369c48cdb47a93aae2b5029d19660183ba944d7bdbc193e54167076d64a3a11ff28e307b84c90eda350edf8e2029195d1fc27ae6055f4
   languageName: node
   linkType: hard
 
 "@types/prop-types@npm:*":
-  version: 15.7.13
-  resolution: "@types/prop-types@npm:15.7.13"
-  checksum: 10c0/1b20fc67281902c6743379960247bc161f3f0406ffc0df8e7058745a85ea1538612109db0406290512947f9632fe9e10e7337bf0ce6338a91d6c948df16a7c61
-  languageName: node
-  linkType: hard
-
-"@types/qs@npm:*":
-  version: 6.9.16
-  resolution: "@types/qs@npm:6.9.16"
-  checksum: 10c0/a4e871b80fff623755e356fd1f225aea45ff7a29da30f99fddee1a05f4f5f33485b314ab5758145144ed45708f97e44595aa9a8368e9bbc083932f931b12dbb6
-  languageName: node
-  linkType: hard
-
-"@types/range-parser@npm:*":
-  version: 1.2.7
-  resolution: "@types/range-parser@npm:1.2.7"
-  checksum: 10c0/361bb3e964ec5133fa40644a0b942279ed5df1949f21321d77de79f48b728d39253e5ce0408c9c17e4e0fd95ca7899da36841686393b9f7a1e209916e9381a3c
+  version: 15.7.14
+  resolution: "@types/prop-types@npm:15.7.14"
+  checksum: 10c0/1ec775160bfab90b67a782d735952158c7e702ca4502968aa82565bd8e452c2de8601c8dfe349733073c31179116cf7340710160d3836aa8a1ef76d1532893b1
   languageName: node
   linkType: hard
 
 "@types/react-dom@npm:^18, @types/react-dom@npm:^18.0.0":
-  version: 18.3.0
-  resolution: "@types/react-dom@npm:18.3.0"
-  dependencies:
-    "@types/react": "npm:*"
-  checksum: 10c0/6c90d2ed72c5a0e440d2c75d99287e4b5df3e7b011838cdc03ae5cd518ab52164d86990e73246b9d812eaf02ec351d74e3b4f5bd325bf341e13bf980392fd53b
+  version: 18.3.5
+  resolution: "@types/react-dom@npm:18.3.5"
+  peerDependencies:
+    "@types/react": ^18.0.0
+  checksum: 10c0/b163d35a6b32a79f5782574a7aeb12a31a647e248792bf437e6d596e2676961c394c5e3c6e91d1ce44ae90441dbaf93158efb4f051c0d61e2612f1cb04ce4faa
   languageName: node
   linkType: hard
 
-"@types/react@npm:*, @types/react@npm:^18":
-  version: 18.3.8
-  resolution: "@types/react@npm:18.3.8"
+"@types/react@npm:^18":
+  version: 18.3.16
+  resolution: "@types/react@npm:18.3.16"
   dependencies:
     "@types/prop-types": "npm:*"
     csstype: "npm:^3.0.2"
-  checksum: 10c0/367312c9fe276639ecb142265e090a4dd04bb39f8d718cbab546de3f1ddcfddeff415e1147d0fc40f734badaa7420b7b109d511bd4304b2c4c9c36164612fdf8
+  checksum: 10c0/9113d3003865eda07be0fb596f5bd8d7784b8900675090c56e75bdee45499f0b0de2481cbbeb5980c3b4ad18f234a49f39c9e62fd7b89a4e8530c74789f739bd
   languageName: node
   linkType: hard
 
@@ -1618,27 +1534,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/send@npm:*":
-  version: 0.17.4
-  resolution: "@types/send@npm:0.17.4"
-  dependencies:
-    "@types/mime": "npm:^1"
-    "@types/node": "npm:*"
-  checksum: 10c0/7f17fa696cb83be0a104b04b424fdedc7eaba1c9a34b06027239aba513b398a0e2b7279778af521f516a397ced417c96960e5f50fcfce40c4bc4509fb1a5883c
-  languageName: node
-  linkType: hard
-
-"@types/serve-static@npm:*":
-  version: 1.15.7
-  resolution: "@types/serve-static@npm:1.15.7"
-  dependencies:
-    "@types/http-errors": "npm:*"
-    "@types/node": "npm:*"
-    "@types/send": "npm:*"
-  checksum: 10c0/26ec864d3a626ea627f8b09c122b623499d2221bbf2f470127f4c9ebfe92bd8a6bb5157001372d4c4bd0dd37a1691620217d9dc4df5aa8f779f3fd996b1c60ae
-  languageName: node
-  linkType: hard
-
 "@types/stack-utils@npm:^2.0.0":
   version: 2.0.3
   resolution: "@types/stack-utils@npm:2.0.3"
@@ -1802,9 +1697,9 @@ __metadata:
   linkType: hard
 
 "@ungap/structured-clone@npm:^1.2.0":
-  version: 1.2.0
-  resolution: "@ungap/structured-clone@npm:1.2.0"
-  checksum: 10c0/8209c937cb39119f44eb63cf90c0b73e7c754209a6411c707be08e50e29ee81356dca1a848a405c8bdeebfe2f5e4f831ad310ae1689eeef65e7445c090c6657d
+  version: 1.2.1
+  resolution: "@ungap/structured-clone@npm:1.2.1"
+  checksum: 10c0/127afbcc75ff1532f7b1eb85ee992f9faa70e8d5bb2558da05355d423b966fc279d0a485bf19da2883280e7c299ae4170809a72e78eab086da71c6bcdda5d1e2
   languageName: node
   linkType: hard
 
@@ -1861,11 +1756,11 @@ __metadata:
   linkType: hard
 
 "acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.4.1, acorn@npm:^8.8.1, acorn@npm:^8.9.0":
-  version: 8.12.1
-  resolution: "acorn@npm:8.12.1"
+  version: 8.14.0
+  resolution: "acorn@npm:8.14.0"
   bin:
     acorn: bin/acorn
-  checksum: 10c0/51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386
+  checksum: 10c0/6d4ee461a7734b2f48836ee0fbb752903606e576cc100eb49340295129ca0b452f3ba91ddd4424a1d4406a98adfb2ebb6bd0ff4c49d7a0930c10e462719bbfd7
   languageName: node
   linkType: hard
 
@@ -1878,22 +1773,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1":
-  version: 7.1.1
-  resolution: "agent-base@npm:7.1.1"
-  dependencies:
-    debug: "npm:^4.3.4"
-  checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50
-  languageName: node
-  linkType: hard
-
-"aggregate-error@npm:^3.0.0":
-  version: 3.1.0
-  resolution: "aggregate-error@npm:3.1.0"
-  dependencies:
-    clean-stack: "npm:^2.0.0"
-    indent-string: "npm:^4.0.0"
-  checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039
+"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2":
+  version: 7.1.3
+  resolution: "agent-base@npm:7.1.3"
+  checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11
   languageName: node
   linkType: hard
 
@@ -1932,15 +1815,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ansi-styles@npm:^3.2.1":
-  version: 3.2.1
-  resolution: "ansi-styles@npm:3.2.1"
-  dependencies:
-    color-convert: "npm:^1.9.0"
-  checksum: 10c0/ece5a8ef069fcc5298f67e3f4771a663129abd174ea2dfa87923a2be2abf6cd367ef72ac87942da00ce85bd1d651d4cd8595aebdb1b385889b89b205860e977b
-  languageName: node
-  linkType: hard
-
 "ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0":
   version: 4.3.0
   resolution: "ansi-styles@npm:4.3.0"
@@ -2011,7 +1885,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"aria-query@npm:5.1.3, aria-query@npm:~5.1.3":
+"aria-query@npm:5.1.3":
   version: 5.1.3
   resolution: "aria-query@npm:5.1.3"
   dependencies:
@@ -2020,7 +1894,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"aria-query@npm:^5.0.0":
+"aria-query@npm:^5.0.0, aria-query@npm:^5.3.2":
   version: 5.3.2
   resolution: "aria-query@npm:5.3.2"
   checksum: 10c0/003c7e3e2cff5540bf7a7893775fc614de82b0c5dde8ae823d47b7a28a9d4da1f7ed85f340bdb93d5649caa927755f0e31ecc7ab63edfdfc00c8ef07e505e03e
@@ -2181,9 +2055,9 @@ __metadata:
   linkType: hard
 
 "axe-core@npm:^4.10.0":
-  version: 4.10.0
-  resolution: "axe-core@npm:4.10.0"
-  checksum: 10c0/732c171d48caaace5e784895c4dacb8ca6155e9d98045138ebe3952f78457dd05b92c57d05b41ce2a570aff87dbd0471e8398d2c0f6ebe79617b746c8f658998
+  version: 4.10.2
+  resolution: "axe-core@npm:4.10.2"
+  checksum: 10c0/0e20169077de96946a547fce0df39d9aeebe0077f9d3eeff4896518b96fde857f80b98f0d4279274a7178791744dd5a54bb4f322de45b4f561ffa2586ff9a09d
   languageName: node
   linkType: hard
 
@@ -2315,17 +2189,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"browserslist@npm:^4.23.1, browserslist@npm:^4.23.3":
-  version: 4.23.3
-  resolution: "browserslist@npm:4.23.3"
+"browserslist@npm:^4.23.3, browserslist@npm:^4.24.0":
+  version: 4.24.2
+  resolution: "browserslist@npm:4.24.2"
   dependencies:
-    caniuse-lite: "npm:^1.0.30001646"
-    electron-to-chromium: "npm:^1.5.4"
+    caniuse-lite: "npm:^1.0.30001669"
+    electron-to-chromium: "npm:^1.5.41"
     node-releases: "npm:^2.0.18"
-    update-browserslist-db: "npm:^1.1.0"
+    update-browserslist-db: "npm:^1.1.1"
   bin:
     browserslist: cli.js
-  checksum: 10c0/3063bfdf812815346447f4796c8f04601bf5d62003374305fd323c2a463e42776475bcc5309264e39bcf9a8605851e53560695991a623be988138b3ff8c66642
+  checksum: 10c0/d747c9fb65ed7b4f1abcae4959405707ed9a7b835639f8a9ba0da2911995a6ab9b0648fd05baf2a4d4e3cf7f9fdbad56d3753f91881e365992c1d49c8d88ff7a
   languageName: node
   linkType: hard
 
@@ -2354,11 +2228,11 @@ __metadata:
   languageName: node
   linkType: hard
 
-"cacache@npm:^18.0.0":
-  version: 18.0.4
-  resolution: "cacache@npm:18.0.4"
+"cacache@npm:^19.0.1":
+  version: 19.0.1
+  resolution: "cacache@npm:19.0.1"
   dependencies:
-    "@npmcli/fs": "npm:^3.1.0"
+    "@npmcli/fs": "npm:^4.0.0"
     fs-minipass: "npm:^3.0.0"
     glob: "npm:^10.2.2"
     lru-cache: "npm:^10.0.1"
@@ -2366,24 +2240,43 @@ __metadata:
     minipass-collect: "npm:^2.0.1"
     minipass-flush: "npm:^1.0.5"
     minipass-pipeline: "npm:^1.2.4"
-    p-map: "npm:^4.0.0"
-    ssri: "npm:^10.0.0"
-    tar: "npm:^6.1.11"
-    unique-filename: "npm:^3.0.0"
-  checksum: 10c0/6c055bafed9de4f3dcc64ac3dc7dd24e863210902b7c470eb9ce55a806309b3efff78033e3d8b4f7dcc5d467f2db43c6a2857aaaf26f0094b8a351d44c42179f
+    p-map: "npm:^7.0.2"
+    ssri: "npm:^12.0.0"
+    tar: "npm:^7.4.3"
+    unique-filename: "npm:^4.0.0"
+  checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c
   languageName: node
   linkType: hard
 
-"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7":
-  version: 1.0.7
-  resolution: "call-bind@npm:1.0.7"
+"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1":
+  version: 1.0.1
+  resolution: "call-bind-apply-helpers@npm:1.0.1"
   dependencies:
-    es-define-property: "npm:^1.0.0"
     es-errors: "npm:^1.3.0"
     function-bind: "npm:^1.1.2"
+  checksum: 10c0/acb2ab68bf2718e68a3e895f0d0b73ccc9e45b9b6f210f163512ba76f91dab409eb8792f6dae188356f9095747512a3101646b3dea9d37fb8c7c6bf37796d18c
+  languageName: node
+  linkType: hard
+
+"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8":
+  version: 1.0.8
+  resolution: "call-bind@npm:1.0.8"
+  dependencies:
+    call-bind-apply-helpers: "npm:^1.0.0"
+    es-define-property: "npm:^1.0.0"
     get-intrinsic: "npm:^1.2.4"
-    set-function-length: "npm:^1.2.1"
-  checksum: 10c0/a3ded2e423b8e2a265983dba81c27e125b48eefb2655e7dfab6be597088da3d47c47976c24bc51b8fd9af1061f8f87b4ab78a314f3c77784b2ae2ba535ad8b8d
+    set-function-length: "npm:^1.2.2"
+  checksum: 10c0/a13819be0681d915144467741b69875ae5f4eba8961eb0bf322aab63ec87f8250eb6d6b0dcbb2e1349876412a56129ca338592b3829ef4343527f5f18a0752d4
+  languageName: node
+  linkType: hard
+
+"call-bound@npm:^1.0.2":
+  version: 1.0.2
+  resolution: "call-bound@npm:1.0.2"
+  dependencies:
+    call-bind: "npm:^1.0.8"
+    get-intrinsic: "npm:^1.2.5"
+  checksum: 10c0/19761e1ce55578f9c41bed06b162de22058d0228cd9c14215d8db73716594ef61b87e5e7486855ea04becd86f55ed08ed81e2c25a4a56962ca12e6b0e772f141
   languageName: node
   linkType: hard
 
@@ -2415,21 +2308,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"caniuse-lite@npm:^1.0.30001579, caniuse-lite@npm:^1.0.30001646":
-  version: 1.0.30001663
-  resolution: "caniuse-lite@npm:1.0.30001663"
-  checksum: 10c0/6508e27bf7fdec657f26f318b1ab64ace6e1208ef9fedaf0975bc89046e0c683bfba837f108840ada1686ff09b8ffd01e05ac791dcf598b8f16eefb636875cf2
-  languageName: node
-  linkType: hard
-
-"chalk@npm:^2.4.2":
-  version: 2.4.2
-  resolution: "chalk@npm:2.4.2"
-  dependencies:
-    ansi-styles: "npm:^3.2.1"
-    escape-string-regexp: "npm:^1.0.5"
-    supports-color: "npm:^5.3.0"
-  checksum: 10c0/e6543f02ec877732e3a2d1c3c3323ddb4d39fbab687c23f526e25bd4c6a9bf3b83a696e8c769d078e04e5754921648f7821b2a2acfd16c550435fd630026e073
+"caniuse-lite@npm:^1.0.30001579, caniuse-lite@npm:^1.0.30001646, caniuse-lite@npm:^1.0.30001669":
+  version: 1.0.30001688
+  resolution: "caniuse-lite@npm:1.0.30001688"
+  checksum: 10c0/2ef3145ac69ea5faf403b613912a3a72006db2e004e58abcf40dc89904aa05568032b5a6dcfb267556944fd380a9b018ad645f93d84e543bed3471e4950a89f4
   languageName: node
   linkType: hard
 
@@ -2460,7 +2342,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"chokidar@npm:^3.5.3":
+"chokidar@npm:^3.6.0":
   version: 3.6.0
   resolution: "chokidar@npm:3.6.0"
   dependencies:
@@ -2479,10 +2361,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"chownr@npm:^2.0.0":
-  version: 2.0.0
-  resolution: "chownr@npm:2.0.0"
-  checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6
+"chownr@npm:^3.0.0":
+  version: 3.0.0
+  resolution: "chownr@npm:3.0.0"
+  checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10
   languageName: node
   linkType: hard
 
@@ -2500,13 +2382,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"clean-stack@npm:^2.0.0":
-  version: 2.2.0
-  resolution: "clean-stack@npm:2.2.0"
-  checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1
-  languageName: node
-  linkType: hard
-
 "client-only@npm:0.0.1, client-only@npm:^0.0.1":
   version: 0.0.1
   resolution: "client-only@npm:0.0.1"
@@ -2539,15 +2414,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"color-convert@npm:^1.9.0":
-  version: 1.9.3
-  resolution: "color-convert@npm:1.9.3"
-  dependencies:
-    color-name: "npm:1.1.3"
-  checksum: 10c0/5ad3c534949a8c68fca8fbc6f09068f435f0ad290ab8b2f76841b9e6af7e0bb57b98cb05b0e19fe33f5d91e5a8611ad457e5f69e0a484caad1f7487fd0e8253c
-  languageName: node
-  linkType: hard
-
 "color-convert@npm:^2.0.1":
   version: 2.0.1
   resolution: "color-convert@npm:2.0.1"
@@ -2557,13 +2423,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"color-name@npm:1.1.3":
-  version: 1.1.3
-  resolution: "color-name@npm:1.1.3"
-  checksum: 10c0/566a3d42cca25b9b3cd5528cd7754b8e89c0eb646b7f214e8e2eaddb69994ac5f0557d9c175eb5d8f0ad73531140d9c47525085ee752a91a2ab15ab459caf6d6
-  languageName: node
-  linkType: hard
-
 "color-name@npm:^1.0.0, color-name@npm:~1.1.4":
   version: 1.1.4
   resolution: "color-name@npm:1.1.4"
@@ -2655,13 +2514,13 @@ __metadata:
   linkType: hard
 
 "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3":
-  version: 7.0.3
-  resolution: "cross-spawn@npm:7.0.3"
+  version: 7.0.6
+  resolution: "cross-spawn@npm:7.0.6"
   dependencies:
     path-key: "npm:^3.1.0"
     shebang-command: "npm:^2.0.0"
     which: "npm:^2.0.1"
-  checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750
+  checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1
   languageName: node
   linkType: hard
 
@@ -2762,7 +2621,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5":
+"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
   version: 4.3.7
   resolution: "debug@npm:4.3.7"
   dependencies:
@@ -2783,6 +2642,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"debug@npm:^4.3.7":
+  version: 4.4.0
+  resolution: "debug@npm:4.4.0"
+  dependencies:
+    ms: "npm:^2.1.3"
+  peerDependenciesMeta:
+    supports-color:
+      optional: true
+  checksum: 10c0/db94f1a182bf886f57b4755f85b3a74c39b5114b9377b7ab375dc2cfa3454f09490cc6c30f829df3fc8042bc8b8995f6567ce5cd96f3bc3688bd24027197d9de
+  languageName: node
+  linkType: hard
+
 "decimal.js@npm:^10.4.2":
   version: 10.4.3
   resolution: "decimal.js@npm:10.4.3"
@@ -2970,6 +2841,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"dunder-proto@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "dunder-proto@npm:1.0.0"
+  dependencies:
+    call-bind-apply-helpers: "npm:^1.0.0"
+    es-errors: "npm:^1.3.0"
+    gopd: "npm:^1.2.0"
+  checksum: 10c0/b321e5cbf64f0a4c786b0b3dc187eb5197a83f6e05a1e11b86db25251b3ae6747c4b805d9e0a4fbf481d22a86a539dc75f82d883daeac7fc2ce4bd72ff5ef5a2
+  languageName: node
+  linkType: hard
+
 "eastasianwidth@npm:^0.2.0":
   version: 0.2.0
   resolution: "eastasianwidth@npm:0.2.0"
@@ -2977,10 +2859,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"electron-to-chromium@npm:^1.5.4":
-  version: 1.5.27
-  resolution: "electron-to-chromium@npm:1.5.27"
-  checksum: 10c0/4a057f469a01829884f2a51f3fc60af7e6a718b15009e4875df122fcdf13babea475ba029af1652a6875b4acfca730c48b13caac5d477d648e622699d3b662bf
+"electron-to-chromium@npm:^1.5.41":
+  version: 1.5.73
+  resolution: "electron-to-chromium@npm:1.5.73"
+  checksum: 10c0/b97118d469f2b3b7a816932004cd36d82879829904ca4a8daf70eaefbe686a23afa6e39e0ad0cdc39d00a9ebab97160d072b786fdeb6964f13fb15aa688958f1
   languageName: node
   linkType: hard
 
@@ -3024,7 +2906,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"entities@npm:^4.4.0":
+"entities@npm:^4.5.0":
   version: 4.5.0
   resolution: "entities@npm:4.5.0"
   checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250
@@ -3054,9 +2936,9 @@ __metadata:
   languageName: node
   linkType: hard
 
-"es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3":
-  version: 1.23.3
-  resolution: "es-abstract@npm:1.23.3"
+"es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5":
+  version: 1.23.5
+  resolution: "es-abstract@npm:1.23.5"
   dependencies:
     array-buffer-byte-length: "npm:^1.0.1"
     arraybuffer.prototype.slice: "npm:^1.0.3"
@@ -3073,7 +2955,7 @@ __metadata:
     function.prototype.name: "npm:^1.1.6"
     get-intrinsic: "npm:^1.2.4"
     get-symbol-description: "npm:^1.0.2"
-    globalthis: "npm:^1.0.3"
+    globalthis: "npm:^1.0.4"
     gopd: "npm:^1.0.1"
     has-property-descriptors: "npm:^1.0.2"
     has-proto: "npm:^1.0.3"
@@ -3089,10 +2971,10 @@ __metadata:
     is-string: "npm:^1.0.7"
     is-typed-array: "npm:^1.1.13"
     is-weakref: "npm:^1.0.2"
-    object-inspect: "npm:^1.13.1"
+    object-inspect: "npm:^1.13.3"
     object-keys: "npm:^1.1.1"
     object.assign: "npm:^4.1.5"
-    regexp.prototype.flags: "npm:^1.5.2"
+    regexp.prototype.flags: "npm:^1.5.3"
     safe-array-concat: "npm:^1.1.2"
     safe-regex-test: "npm:^1.0.3"
     string.prototype.trim: "npm:^1.2.9"
@@ -3104,16 +2986,14 @@ __metadata:
     typed-array-length: "npm:^1.0.6"
     unbox-primitive: "npm:^1.0.2"
     which-typed-array: "npm:^1.1.15"
-  checksum: 10c0/d27e9afafb225c6924bee9971a7f25f20c314f2d6cb93a63cada4ac11dcf42040896a6c22e5fb8f2a10767055ed4ddf400be3b1eb12297d281726de470b75666
+  checksum: 10c0/1f6f91da9cf7ee2c81652d57d3046621d598654d1d1b05c1578bafe5c4c2d3d69513901679bdca2de589f620666ec21de337e4935cec108a4ed0871d5ef04a5d
   languageName: node
   linkType: hard
 
-"es-define-property@npm:^1.0.0":
-  version: 1.0.0
-  resolution: "es-define-property@npm:1.0.0"
-  dependencies:
-    get-intrinsic: "npm:^1.2.4"
-  checksum: 10c0/6bf3191feb7ea2ebda48b577f69bdfac7a2b3c9bcf97307f55fd6ef1bbca0b49f0c219a935aca506c993d8c5d8bddd937766cb760cd5e5a1071351f2df9f9aa4
+"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1":
+  version: 1.0.1
+  resolution: "es-define-property@npm:1.0.1"
+  checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c
   languageName: node
   linkType: hard
 
@@ -3141,9 +3021,9 @@ __metadata:
   languageName: node
   linkType: hard
 
-"es-iterator-helpers@npm:^1.0.19":
-  version: 1.0.19
-  resolution: "es-iterator-helpers@npm:1.0.19"
+"es-iterator-helpers@npm:^1.1.0":
+  version: 1.2.0
+  resolution: "es-iterator-helpers@npm:1.2.0"
   dependencies:
     call-bind: "npm:^1.0.7"
     define-properties: "npm:^1.2.1"
@@ -3152,14 +3032,15 @@ __metadata:
     es-set-tostringtag: "npm:^2.0.3"
     function-bind: "npm:^1.1.2"
     get-intrinsic: "npm:^1.2.4"
-    globalthis: "npm:^1.0.3"
+    globalthis: "npm:^1.0.4"
+    gopd: "npm:^1.0.1"
     has-property-descriptors: "npm:^1.0.2"
     has-proto: "npm:^1.0.3"
     has-symbols: "npm:^1.0.3"
     internal-slot: "npm:^1.0.7"
-    iterator.prototype: "npm:^1.1.2"
+    iterator.prototype: "npm:^1.1.3"
     safe-array-concat: "npm:^1.1.2"
-  checksum: 10c0/ae8f0241e383b3d197383b9842c48def7fce0255fb6ed049311b686ce295595d9e389b466f6a1b7d4e7bb92d82f5e716d6fae55e20c1040249bf976743b038c5
+  checksum: 10c0/2bd60580dfeae353f5b80445d2808da745e97eeacdb663a8c4d99a12046873830a06d377e9d5e88fe54eece7c94319a5ce5a01220e24d71394ceca8d3ef621d7
   languageName: node
   linkType: hard
 
@@ -3193,30 +3074,23 @@ __metadata:
   linkType: hard
 
 "es-to-primitive@npm:^1.2.1":
-  version: 1.2.1
-  resolution: "es-to-primitive@npm:1.2.1"
+  version: 1.3.0
+  resolution: "es-to-primitive@npm:1.3.0"
   dependencies:
-    is-callable: "npm:^1.1.4"
-    is-date-object: "npm:^1.0.1"
-    is-symbol: "npm:^1.0.2"
-  checksum: 10c0/0886572b8dc075cb10e50c0af62a03d03a68e1e69c388bd4f10c0649ee41b1fbb24840a1b7e590b393011b5cdbe0144b776da316762653685432df37d6de60f1
+    is-callable: "npm:^1.2.7"
+    is-date-object: "npm:^1.0.5"
+    is-symbol: "npm:^1.0.4"
+  checksum: 10c0/c7e87467abb0b438639baa8139f701a06537d2b9bc758f23e8622c3b42fd0fdb5bde0f535686119e446dd9d5e4c0f238af4e14960f4771877cf818d023f6730b
   languageName: node
   linkType: hard
 
-"escalade@npm:^3.1.1, escalade@npm:^3.1.2":
+"escalade@npm:^3.1.1, escalade@npm:^3.2.0":
   version: 3.2.0
   resolution: "escalade@npm:3.2.0"
   checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65
   languageName: node
   linkType: hard
 
-"escape-string-regexp@npm:^1.0.5":
-  version: 1.0.5
-  resolution: "escape-string-regexp@npm:1.0.5"
-  checksum: 10c0/a968ad453dd0c2724e14a4f20e177aaf32bb384ab41b674a8454afe9a41c5e6fe8903323e0a1052f56289d04bd600f81278edf140b0fcc02f5cac98d0f5b5371
-  languageName: node
-  linkType: hard
-
 "escape-string-regexp@npm:^2.0.0":
   version: 2.0.0
   resolution: "escape-string-regexp@npm:2.0.0"
@@ -3317,17 +3191,17 @@ __metadata:
   linkType: hard
 
 "eslint-import-resolver-typescript@npm:^3.5.2":
-  version: 3.6.3
-  resolution: "eslint-import-resolver-typescript@npm:3.6.3"
+  version: 3.7.0
+  resolution: "eslint-import-resolver-typescript@npm:3.7.0"
   dependencies:
     "@nolyfill/is-core-module": "npm:1.0.39"
-    debug: "npm:^4.3.5"
+    debug: "npm:^4.3.7"
     enhanced-resolve: "npm:^5.15.0"
-    eslint-module-utils: "npm:^2.8.1"
     fast-glob: "npm:^3.3.2"
     get-tsconfig: "npm:^4.7.5"
     is-bun-module: "npm:^1.0.2"
     is-glob: "npm:^4.0.3"
+    stable-hash: "npm:^0.0.4"
   peerDependencies:
     eslint: "*"
     eslint-plugin-import: "*"
@@ -3337,19 +3211,19 @@ __metadata:
       optional: true
     eslint-plugin-import-x:
       optional: true
-  checksum: 10c0/5933b00791b7b077725b9ba9a85327d2e2dc7c8944c18a868feb317a0bf0e1e77aed2254c9c5e24dcc49360d119331d2c15281837f4269592965ace380a75111
+  checksum: 10c0/b1dec542a31486b3b5730f71f08a8ee2ac4915dbc4aa1493fd15bc8fcadcb029772ab39a425824c235045b3a7e629290a339d4a7e7f3dd32b24e715106352d40
   languageName: node
   linkType: hard
 
-"eslint-module-utils@npm:^2.8.1, eslint-module-utils@npm:^2.9.0":
-  version: 2.11.0
-  resolution: "eslint-module-utils@npm:2.11.0"
+"eslint-module-utils@npm:^2.12.0":
+  version: 2.12.0
+  resolution: "eslint-module-utils@npm:2.12.0"
   dependencies:
     debug: "npm:^3.2.7"
   peerDependenciesMeta:
     eslint:
       optional: true
-  checksum: 10c0/c1b02e83429878ab22596f17a5ac138e51a520e96a5ef89a5a6698769a2d174ab28302d45eb563c0fc418d21a5842e328c37a6e8f294bf2e64e675ba55203dd7
+  checksum: 10c0/4d8b46dcd525d71276f9be9ffac1d2be61c9d54cc53c992e6333cf957840dee09381842b1acbbb15fc6b255ebab99cd481c5007ab438e5455a14abe1a0468558
   languageName: node
   linkType: hard
 
@@ -3366,18 +3240,18 @@ __metadata:
   linkType: hard
 
 "eslint-plugin-i18next@npm:^6.0.3":
-  version: 6.1.0
-  resolution: "eslint-plugin-i18next@npm:6.1.0"
+  version: 6.1.1
+  resolution: "eslint-plugin-i18next@npm:6.1.1"
   dependencies:
     lodash: "npm:^4.17.21"
     requireindex: "npm:~1.1.0"
-  checksum: 10c0/06c36df0de8cc0043c54c3e881d89b51558ed0b8c9dbff6f9cc9028e8df789a254921b7fad1427ce25790bbd8b99089ae413f95742e3536992be6e709cdee302
+  checksum: 10c0/38b29ad0a8385ab4b9cb7667b8ae082fdf59757d697c2532a324a216ebaa0e0b309ef4088741e42aff8160e186b5076cfa0cc159e0fd869aaf79f443608ea8d8
   languageName: node
   linkType: hard
 
 "eslint-plugin-import@npm:^2.27.5, eslint-plugin-import@npm:^2.28.1":
-  version: 2.30.0
-  resolution: "eslint-plugin-import@npm:2.30.0"
+  version: 2.31.0
+  resolution: "eslint-plugin-import@npm:2.31.0"
   dependencies:
     "@rtsao/scc": "npm:^1.1.0"
     array-includes: "npm:^3.1.8"
@@ -3387,7 +3261,7 @@ __metadata:
     debug: "npm:^3.2.7"
     doctrine: "npm:^2.1.0"
     eslint-import-resolver-node: "npm:^0.3.9"
-    eslint-module-utils: "npm:^2.9.0"
+    eslint-module-utils: "npm:^2.12.0"
     hasown: "npm:^2.0.2"
     is-core-module: "npm:^2.15.1"
     is-glob: "npm:^4.0.3"
@@ -3396,18 +3270,19 @@ __metadata:
     object.groupby: "npm:^1.0.3"
     object.values: "npm:^1.2.0"
     semver: "npm:^6.3.1"
+    string.prototype.trimend: "npm:^1.0.8"
     tsconfig-paths: "npm:^3.15.0"
   peerDependencies:
-    eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
-  checksum: 10c0/4c9dcb1f27505c4d5dd891d2b551f56c70786d136aa3992a77e785bdc67c9f60200a2c7fb0ce55b7647fe550b12bc433d5dfa59e2c00ab44227791c5ab86badf
+    eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
+  checksum: 10c0/e21d116ddd1900e091ad120b3eb68c5dd5437fe2c930f1211781cd38b246f090a6b74d5f3800b8255a0ed29782591521ad44eb21c5534960a8f1fb4040fd913a
   languageName: node
   linkType: hard
 
 "eslint-plugin-jsx-a11y@npm:^6.7.1":
-  version: 6.10.0
-  resolution: "eslint-plugin-jsx-a11y@npm:6.10.0"
+  version: 6.10.2
+  resolution: "eslint-plugin-jsx-a11y@npm:6.10.2"
   dependencies:
-    aria-query: "npm:~5.1.3"
+    aria-query: "npm:^5.3.2"
     array-includes: "npm:^3.1.8"
     array.prototype.flatmap: "npm:^1.3.2"
     ast-types-flow: "npm:^0.0.8"
@@ -3415,17 +3290,16 @@ __metadata:
     axobject-query: "npm:^4.1.0"
     damerau-levenshtein: "npm:^1.0.8"
     emoji-regex: "npm:^9.2.2"
-    es-iterator-helpers: "npm:^1.0.19"
     hasown: "npm:^2.0.2"
     jsx-ast-utils: "npm:^3.3.5"
     language-tags: "npm:^1.0.9"
     minimatch: "npm:^3.1.2"
     object.fromentries: "npm:^2.0.8"
     safe-regex-test: "npm:^1.0.3"
-    string.prototype.includes: "npm:^2.0.0"
+    string.prototype.includes: "npm:^2.0.1"
   peerDependencies:
     eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
-  checksum: 10c0/9f8e29a3317fb6a82e2ecd333fe0fab3a69fff786d087eb65dc723d6e954473ab681d14a252d7cb2971f5e7f68816cb6f7731766558e1833a77bd73af1b5ab34
+  checksum: 10c0/d93354e03b0cf66f018d5c50964e074dffe4ddf1f9b535fa020d19c4ae45f89c1a16e9391ca61ac3b19f7042c751ac0d361a056a65cbd1de24718a53ff8daa6e
   languageName: node
   linkType: hard
 
@@ -3484,15 +3358,15 @@ __metadata:
   linkType: hard
 
 "eslint-plugin-react@npm:^7.32.2, eslint-plugin-react@npm:^7.33.2":
-  version: 7.36.1
-  resolution: "eslint-plugin-react@npm:7.36.1"
+  version: 7.37.2
+  resolution: "eslint-plugin-react@npm:7.37.2"
   dependencies:
     array-includes: "npm:^3.1.8"
     array.prototype.findlast: "npm:^1.2.5"
     array.prototype.flatmap: "npm:^1.3.2"
     array.prototype.tosorted: "npm:^1.1.4"
     doctrine: "npm:^2.1.0"
-    es-iterator-helpers: "npm:^1.0.19"
+    es-iterator-helpers: "npm:^1.1.0"
     estraverse: "npm:^5.3.0"
     hasown: "npm:^2.0.2"
     jsx-ast-utils: "npm:^2.4.1 || ^3.0.0"
@@ -3507,7 +3381,7 @@ __metadata:
     string.prototype.repeat: "npm:^1.0.0"
   peerDependencies:
     eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
-  checksum: 10c0/8cb37f7fb351213bc44263580ff77627e14e27870fd81dae593e3de2826340b9bd8bbac7ae00fd5de69751a0660b2e51bd26760596f4ae85548f6b1bd76706e6
+  checksum: 10c0/01c498f263c201698bf653973760f86a07fa0cdec56c044f3eaa5ddaae71c64326015dfa5fde76ca8c5386ffe789fc79932624b614e13b6a1ad789fee3f7c491
   languageName: node
   linkType: hard
 
@@ -3559,7 +3433,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3":
+"eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3":
   version: 3.4.3
   resolution: "eslint-visitor-keys@npm:3.4.3"
   checksum: 10c0/92708e882c0a5ffd88c23c0b404ac1628cf20104a108c745f240a13c332a11aac54f49a22d5762efbffc18ecbc9a580d1b7ad034bf5f3cc3307e5cbff2ec9820
@@ -3725,7 +3599,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.2":
+"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2":
   version: 3.3.2
   resolution: "fast-glob@npm:3.3.2"
   dependencies:
@@ -3820,9 +3694,9 @@ __metadata:
   linkType: hard
 
 "flatted@npm:^3.2.9":
-  version: 3.3.1
-  resolution: "flatted@npm:3.3.1"
-  checksum: 10c0/324166b125ee07d4ca9bcf3a5f98d915d5db4f39d711fba640a3178b959919aae1f7cfd8aabcfef5826ed8aa8a2aa14cc85b2d7d18ff638ddf4ae3df39573eaf
+  version: 3.3.2
+  resolution: "flatted@npm:3.3.2"
+  checksum: 10c0/24cc735e74d593b6c767fe04f2ef369abe15b62f6906158079b9874bdb3ee5ae7110bb75042e70cd3f99d409d766f357caf78d5ecee9780206f5fdc5edbad334
   languageName: node
   linkType: hard
 
@@ -3846,13 +3720,13 @@ __metadata:
   linkType: hard
 
 "form-data@npm:^4.0.0":
-  version: 4.0.0
-  resolution: "form-data@npm:4.0.0"
+  version: 4.0.1
+  resolution: "form-data@npm:4.0.1"
   dependencies:
     asynckit: "npm:^0.4.0"
     combined-stream: "npm:^1.0.8"
     mime-types: "npm:^2.1.12"
-  checksum: 10c0/cb6f3ac49180be03ff07ba3ff125f9eba2ff0b277fb33c7fc47569fc5e616882c5b1c69b9904c4c4187e97dd0419dd03b134174756f296dec62041e6527e2c6e
+  checksum: 10c0/bb102d570be8592c23f4ea72d7df9daa50c7792eb0cf1c5d7e506c1706e7426a4e4ae48a35b109e91c85f1c0ec63774a21ae252b66f4eb981cb8efef7d0463c8
   languageName: node
   linkType: hard
 
@@ -3870,15 +3744,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"fs-minipass@npm:^2.0.0":
-  version: 2.1.0
-  resolution: "fs-minipass@npm:2.1.0"
-  dependencies:
-    minipass: "npm:^3.0.0"
-  checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004
-  languageName: node
-  linkType: hard
-
 "fs-minipass@npm:^3.0.0":
   version: 3.0.3
   resolution: "fs-minipass@npm:3.0.3"
@@ -3954,16 +3819,21 @@ __metadata:
   languageName: node
   linkType: hard
 
-"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4":
-  version: 1.2.4
-  resolution: "get-intrinsic@npm:1.2.4"
+"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6":
+  version: 1.2.6
+  resolution: "get-intrinsic@npm:1.2.6"
   dependencies:
+    call-bind-apply-helpers: "npm:^1.0.1"
+    dunder-proto: "npm:^1.0.0"
+    es-define-property: "npm:^1.0.1"
     es-errors: "npm:^1.3.0"
+    es-object-atoms: "npm:^1.0.0"
     function-bind: "npm:^1.1.2"
-    has-proto: "npm:^1.0.1"
-    has-symbols: "npm:^1.0.3"
-    hasown: "npm:^2.0.0"
-  checksum: 10c0/0a9b82c16696ed6da5e39b1267104475c47e3a9bdbe8b509dfe1710946e38a87be70d759f4bb3cda042d76a41ef47fe769660f3b7c0d1f68750299344ffb15b7
+    gopd: "npm:^1.2.0"
+    has-symbols: "npm:^1.1.0"
+    hasown: "npm:^2.0.2"
+    math-intrinsics: "npm:^1.0.0"
+  checksum: 10c0/0f1ea6d807d97d074e8a31ac698213a12757fcfa9a8f4778263d2e4702c40fe83198aadd3dba2e99aabc2e4cf8a38345545dbb0518297d3df8b00b56a156c32a
   languageName: node
   linkType: hard
 
@@ -4034,7 +3904,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"glob@npm:^10.2.2, glob@npm:^10.3.10":
+"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7":
   version: 10.4.5
   resolution: "glob@npm:10.4.5"
   dependencies:
@@ -4080,7 +3950,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"globalthis@npm:^1.0.3":
+"globalthis@npm:^1.0.4":
   version: 1.0.4
   resolution: "globalthis@npm:1.0.4"
   dependencies:
@@ -4104,12 +3974,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"gopd@npm:^1.0.1":
-  version: 1.0.1
-  resolution: "gopd@npm:1.0.1"
-  dependencies:
-    get-intrinsic: "npm:^1.1.3"
-  checksum: 10c0/505c05487f7944c552cee72087bf1567debb470d4355b1335f2c262d218ebbff805cd3715448fe29b4b380bae6912561d0467233e4165830efd28da241418c63
+"gopd@npm:^1.0.1, gopd@npm:^1.2.0":
+  version: 1.2.0
+  resolution: "gopd@npm:1.2.0"
+  checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead
   languageName: node
   linkType: hard
 
@@ -4127,20 +3995,13 @@ __metadata:
   languageName: node
   linkType: hard
 
-"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2":
+"has-bigints@npm:^1.0.2":
   version: 1.0.2
   resolution: "has-bigints@npm:1.0.2"
   checksum: 10c0/724eb1485bfa3cdff6f18d95130aa190561f00b3fcf9f19dc640baf8176b5917c143b81ec2123f8cddb6c05164a198c94b13e1377c497705ccc8e1a80306e83b
   languageName: node
   linkType: hard
 
-"has-flag@npm:^3.0.0":
-  version: 3.0.0
-  resolution: "has-flag@npm:3.0.0"
-  checksum: 10c0/1c6c83b14b8b1b3c25b0727b8ba3e3b647f99e9e6e13eb7322107261de07a4c1be56fc0d45678fc376e09772a3a1642ccdaf8fc69bdf123b6c086598397ce473
-  languageName: node
-  linkType: hard
-
 "has-flag@npm:^4.0.0":
   version: 4.0.0
   resolution: "has-flag@npm:4.0.0"
@@ -4157,17 +4018,19 @@ __metadata:
   languageName: node
   linkType: hard
 
-"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3":
-  version: 1.0.3
-  resolution: "has-proto@npm:1.0.3"
-  checksum: 10c0/35a6989f81e9f8022c2f4027f8b48a552de714938765d019dbea6bb547bd49ce5010a3c7c32ec6ddac6e48fc546166a3583b128f5a7add8b058a6d8b4afec205
+"has-proto@npm:^1.0.3":
+  version: 1.2.0
+  resolution: "has-proto@npm:1.2.0"
+  dependencies:
+    dunder-proto: "npm:^1.0.0"
+  checksum: 10c0/46538dddab297ec2f43923c3d35237df45d8c55a6fc1067031e04c13ed8a9a8f94954460632fd4da84c31a1721eefee16d901cbb1ae9602bab93bb6e08f93b95
   languageName: node
   linkType: hard
 
-"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3":
-  version: 1.0.3
-  resolution: "has-symbols@npm:1.0.3"
-  checksum: 10c0/e6922b4345a3f37069cdfe8600febbca791c94988c01af3394d86ca3360b4b93928bbf395859158f88099cb10b19d98e3bbab7c9ff2c1bd09cf665ee90afa2c3
+"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "has-symbols@npm:1.1.0"
+  checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e
   languageName: node
   linkType: hard
 
@@ -4244,12 +4107,12 @@ __metadata:
   linkType: hard
 
 "https-proxy-agent@npm:^7.0.1":
-  version: 7.0.5
-  resolution: "https-proxy-agent@npm:7.0.5"
+  version: 7.0.6
+  resolution: "https-proxy-agent@npm:7.0.6"
   dependencies:
-    agent-base: "npm:^7.0.2"
+    agent-base: "npm:^7.1.2"
     debug: "npm:4"
-  checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c
+  checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac
   languageName: node
   linkType: hard
 
@@ -4261,11 +4124,11 @@ __metadata:
   linkType: hard
 
 "husky@npm:^9.0.11":
-  version: 9.1.6
-  resolution: "husky@npm:9.1.6"
+  version: 9.1.7
+  resolution: "husky@npm:9.1.7"
   bin:
     husky: bin.js
-  checksum: 10c0/705673db4a247c1febd9c5df5f6a3519106cf0335845027bb50a15fba9b1f542cb2610932ede96fd08008f6d9f49db0f15560509861808b0031cdc0e7c798bac
+  checksum: 10c0/35bb110a71086c48906aa7cd3ed4913fb913823715359d65e32e0b964cb1e255593b0ae8014a5005c66a68e6fa66c38dcfa8056dbbdfb8b0187c0ffe7ee3a58f
   languageName: node
   linkType: hard
 
@@ -4372,12 +4235,12 @@ __metadata:
   linkType: hard
 
 "is-arguments@npm:^1.1.1":
-  version: 1.1.1
-  resolution: "is-arguments@npm:1.1.1"
+  version: 1.2.0
+  resolution: "is-arguments@npm:1.2.0"
   dependencies:
-    call-bind: "npm:^1.0.2"
-    has-tostringtag: "npm:^1.0.0"
-  checksum: 10c0/5ff1f341ee4475350adfc14b2328b38962564b7c2076be2f5bac7bd9b61779efba99b9f844a7b82ba7654adccf8e8eb19d1bb0cc6d1c1a085e498f6793d4328f
+    call-bound: "npm:^1.0.2"
+    has-tostringtag: "npm:^1.0.2"
+  checksum: 10c0/6377344b31e9fcb707c6751ee89b11f132f32338e6a782ec2eac9393b0cbd32235dad93052998cda778ee058754860738341d8114910d50ada5615912bb929fc
   languageName: node
   linkType: hard
 
@@ -4414,12 +4277,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-bigint@npm:^1.0.1":
-  version: 1.0.4
-  resolution: "is-bigint@npm:1.0.4"
+"is-bigint@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "is-bigint@npm:1.1.0"
   dependencies:
-    has-bigints: "npm:^1.0.1"
-  checksum: 10c0/eb9c88e418a0d195ca545aff2b715c9903d9b0a5033bc5922fec600eb0c3d7b1ee7f882dbf2e0d5a6e694e42391be3683e4368737bd3c4a77f8ac293e7773696
+    has-bigints: "npm:^1.0.2"
+  checksum: 10c0/f4f4b905ceb195be90a6ea7f34323bf1c18e3793f18922e3e9a73c684c29eeeeff5175605c3a3a74cc38185fe27758f07efba3dbae812e5c5afbc0d2316b40e4
   languageName: node
   linkType: hard
 
@@ -4432,26 +4295,26 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-boolean-object@npm:^1.1.0":
-  version: 1.1.2
-  resolution: "is-boolean-object@npm:1.1.2"
+"is-boolean-object@npm:^1.2.0":
+  version: 1.2.1
+  resolution: "is-boolean-object@npm:1.2.1"
   dependencies:
-    call-bind: "npm:^1.0.2"
-    has-tostringtag: "npm:^1.0.0"
-  checksum: 10c0/6090587f8a8a8534c0f816da868bc94f32810f08807aa72fa7e79f7e11c466d281486ffe7a788178809c2aa71fe3e700b167fe80dd96dad68026bfff8ebf39f7
+    call-bound: "npm:^1.0.2"
+    has-tostringtag: "npm:^1.0.2"
+  checksum: 10c0/2ef601d255a39fdbde79cfe6be80c27b47430ed6712407f29b17d002e20f64c1e3d6692f1d842ba16bf1e9d8ddf1c4f13cac3ed7d9a4a21290f44879ebb4e8f5
   languageName: node
   linkType: hard
 
 "is-bun-module@npm:^1.0.2":
-  version: 1.2.1
-  resolution: "is-bun-module@npm:1.2.1"
+  version: 1.3.0
+  resolution: "is-bun-module@npm:1.3.0"
   dependencies:
     semver: "npm:^7.6.3"
-  checksum: 10c0/819e63cd4468265a3e89cdc241554e37aeb85e40375a56dd559c022f4395491273267a0f843274fda6cad1eac3b0f8dc6d9e06cc349e33e2bf45098761184736
+  checksum: 10c0/2966744188fcd28e0123c52158c7073973f88babfa9ab04e2846ec5862d6b0f8f398df6413429d930f7c5ee6111ce2cbfb3eb8652d9ec42d4a37dc5089a866fb
   languageName: node
   linkType: hard
 
-"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7":
+"is-callable@npm:^1.1.3, is-callable@npm:^1.2.7":
   version: 1.2.7
   resolution: "is-callable@npm:1.2.7"
   checksum: 10c0/ceebaeb9d92e8adee604076971dd6000d38d6afc40bb843ea8e45c5579b57671c3f3b50d7f04869618242c6cee08d1b67806a8cb8edaaaf7c0748b3720d6066f
@@ -4468,20 +4331,23 @@ __metadata:
   linkType: hard
 
 "is-data-view@npm:^1.0.1":
-  version: 1.0.1
-  resolution: "is-data-view@npm:1.0.1"
+  version: 1.0.2
+  resolution: "is-data-view@npm:1.0.2"
   dependencies:
+    call-bound: "npm:^1.0.2"
+    get-intrinsic: "npm:^1.2.6"
     is-typed-array: "npm:^1.1.13"
-  checksum: 10c0/a3e6ec84efe303da859107aed9b970e018e2bee7ffcb48e2f8096921a493608134240e672a2072577e5f23a729846241d9634806e8a0e51d9129c56d5f65442d
+  checksum: 10c0/ef3548a99d7e7f1370ce21006baca6d40c73e9f15c941f89f0049c79714c873d03b02dae1c64b3f861f55163ecc16da06506c5b8a1d4f16650b3d9351c380153
   languageName: node
   linkType: hard
 
-"is-date-object@npm:^1.0.1, is-date-object@npm:^1.0.5":
-  version: 1.0.5
-  resolution: "is-date-object@npm:1.0.5"
+"is-date-object@npm:^1.0.5, is-date-object@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "is-date-object@npm:1.1.0"
   dependencies:
-    has-tostringtag: "npm:^1.0.0"
-  checksum: 10c0/eed21e5dcc619c48ccef804dfc83a739dbb2abee6ca202838ee1bd5f760fe8d8a93444f0d49012ad19bb7c006186e2884a1b92f6e1c056da7fd23d0a9ad5992e
+    call-bound: "npm:^1.0.2"
+    has-tostringtag: "npm:^1.0.2"
+  checksum: 10c0/1a4d199c8e9e9cac5128d32e6626fa7805175af9df015620ac0d5d45854ccf348ba494679d872d37301032e35a54fc7978fba1687e8721b2139aea7870cafa2f
   languageName: node
   linkType: hard
 
@@ -4492,12 +4358,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-finalizationregistry@npm:^1.0.2":
-  version: 1.0.2
-  resolution: "is-finalizationregistry@npm:1.0.2"
+"is-finalizationregistry@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "is-finalizationregistry@npm:1.1.0"
   dependencies:
-    call-bind: "npm:^1.0.2"
-  checksum: 10c0/81caecc984d27b1a35c68741156fc651fb1fa5e3e6710d21410abc527eb226d400c0943a167922b2e920f6b3e58b0dede9aa795882b038b85f50b3a4b877db86
+    call-bind: "npm:^1.0.7"
+  checksum: 10c0/1cd94236bfb6e060fe2b973c8726a2782727f7d495b3e8e1d51d3e619c5a3345413706f555956eb5b12af15eba0414118f64a1b19d793ec36b5e6767a13836ac
   languageName: node
   linkType: hard
 
@@ -4533,13 +4399,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-lambda@npm:^1.0.1":
-  version: 1.0.1
-  resolution: "is-lambda@npm:1.0.1"
-  checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d
-  languageName: node
-  linkType: hard
-
 "is-map@npm:^2.0.2, is-map@npm:^2.0.3":
   version: 2.0.3
   resolution: "is-map@npm:2.0.3"
@@ -4554,12 +4413,13 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-number-object@npm:^1.0.4":
-  version: 1.0.7
-  resolution: "is-number-object@npm:1.0.7"
+"is-number-object@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "is-number-object@npm:1.1.0"
   dependencies:
-    has-tostringtag: "npm:^1.0.0"
-  checksum: 10c0/aad266da1e530f1804a2b7bd2e874b4869f71c98590b3964f9d06cc9869b18f8d1f4778f838ecd2a11011bce20aeecb53cb269ba916209b79c24580416b74b1b
+    call-bind: "npm:^1.0.7"
+    has-tostringtag: "npm:^1.0.2"
+  checksum: 10c0/29d575b5c54ff13f824858d8f7da4cf27131c59858744ec94e96be7b7d2de81038971c15a2636b38fa9eece3797c14bf8de898e1b30afc2f5c1df5cea9f06a8e
   languageName: node
   linkType: hard
 
@@ -4584,13 +4444,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-regex@npm:^1.1.4":
-  version: 1.1.4
-  resolution: "is-regex@npm:1.1.4"
+"is-regex@npm:^1.1.4, is-regex@npm:^1.2.1":
+  version: 1.2.1
+  resolution: "is-regex@npm:1.2.1"
   dependencies:
-    call-bind: "npm:^1.0.2"
-    has-tostringtag: "npm:^1.0.0"
-  checksum: 10c0/bb72aae604a69eafd4a82a93002058c416ace8cde95873589a97fc5dac96a6c6c78a9977d487b7b95426a8f5073969124dd228f043f9f604f041f32fcc465fc1
+    call-bound: "npm:^1.0.2"
+    gopd: "npm:^1.2.0"
+    has-tostringtag: "npm:^1.0.2"
+    hasown: "npm:^2.0.2"
+  checksum: 10c0/1d3715d2b7889932349241680032e85d0b492cfcb045acb75ffc2c3085e8d561184f1f7e84b6f8321935b4aea39bc9c6ba74ed595b57ce4881a51dfdbc214e04
   languageName: node
   linkType: hard
 
@@ -4617,21 +4479,24 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-string@npm:^1.0.5, is-string@npm:^1.0.7":
-  version: 1.0.7
-  resolution: "is-string@npm:1.0.7"
+"is-string@npm:^1.0.7, is-string@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "is-string@npm:1.1.0"
   dependencies:
-    has-tostringtag: "npm:^1.0.0"
-  checksum: 10c0/905f805cbc6eedfa678aaa103ab7f626aac9ebbdc8737abb5243acaa61d9820f8edc5819106b8fcd1839e33db21de9f0116ae20de380c8382d16dc2a601921f6
+    call-bind: "npm:^1.0.7"
+    has-tostringtag: "npm:^1.0.2"
+  checksum: 10c0/2781bce7bfdb00276d000a7aafccad8038a7b5cb06abbfc638417a705dd41bca259977af78731dc8a87f170783c94c9f684bc086fc4856b623c1fd942c509b6b
   languageName: node
   linkType: hard
 
-"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3":
-  version: 1.0.4
-  resolution: "is-symbol@npm:1.0.4"
+"is-symbol@npm:^1.0.4, is-symbol@npm:^1.1.0":
+  version: 1.1.1
+  resolution: "is-symbol@npm:1.1.1"
   dependencies:
-    has-symbols: "npm:^1.0.2"
-  checksum: 10c0/9381dd015f7c8906154dbcbf93fad769de16b4b961edc94f88d26eb8c555935caa23af88bda0c93a18e65560f6d7cca0fd5a3f8a8e1df6f1abbb9bead4502ef7
+    call-bound: "npm:^1.0.2"
+    has-symbols: "npm:^1.1.0"
+    safe-regex-test: "npm:^1.1.0"
+  checksum: 10c0/f08f3e255c12442e833f75a9e2b84b2d4882fdfd920513cf2a4a2324f0a5b076c8fd913778e3ea5d258d5183e9d92c0cd20e04b03ab3df05316b049b2670af1e
   languageName: node
   linkType: hard
 
@@ -4766,16 +4631,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"iterator.prototype@npm:^1.1.2":
-  version: 1.1.2
-  resolution: "iterator.prototype@npm:1.1.2"
+"iterator.prototype@npm:^1.1.3":
+  version: 1.1.4
+  resolution: "iterator.prototype@npm:1.1.4"
   dependencies:
-    define-properties: "npm:^1.2.1"
-    get-intrinsic: "npm:^1.2.1"
-    has-symbols: "npm:^1.0.3"
-    reflect.getprototypeof: "npm:^1.0.4"
-    set-function-name: "npm:^2.0.1"
-  checksum: 10c0/a32151326095e916f306990d909f6bbf23e3221999a18ba686419535dcd1749b10ded505e89334b77dc4c7a58a8508978f0eb16c2c8573e6d412eb7eb894ea79
+    define-data-property: "npm:^1.1.4"
+    es-object-atoms: "npm:^1.0.0"
+    get-intrinsic: "npm:^1.2.6"
+    has-symbols: "npm:^1.1.0"
+    reflect.getprototypeof: "npm:^1.0.8"
+    set-function-name: "npm:^2.0.2"
+  checksum: 10c0/e63fcb5c1094192f43795b836fae9149a7dc2d445425958045e8e193df428407f909efca21bfdf0d885668ae8204681984afac7dd75478118e62f3cd3959c538
   languageName: node
   linkType: hard
 
@@ -5265,7 +5131,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"jiti@npm:^1.21.0":
+"jiti@npm:^1.21.6":
   version: 1.21.6
   resolution: "jiti@npm:1.21.6"
   bin:
@@ -5274,6 +5140,21 @@ __metadata:
   languageName: node
   linkType: hard
 
+"jotai@npm:^2.10.3":
+  version: 2.10.3
+  resolution: "jotai@npm:2.10.3"
+  peerDependencies:
+    "@types/react": ">=17.0.0"
+    react: ">=17.0.0"
+  peerDependenciesMeta:
+    "@types/react":
+      optional: true
+    react:
+      optional: true
+  checksum: 10c0/64f6536aaa91f77dacd8d9714fb846f254bfed6e5354b3005375433d72844f3ae1d6d893ee4dd423d5bddd109d393dd338e562da914605b31190989a3d47db35
+  languageName: node
+  linkType: hard
+
 "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0":
   version: 4.0.0
   resolution: "js-tokens@npm:4.0.0"
@@ -5350,12 +5231,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"jsesc@npm:^2.5.1":
-  version: 2.5.2
-  resolution: "jsesc@npm:2.5.2"
+"jsesc@npm:^3.0.2":
+  version: 3.1.0
+  resolution: "jsesc@npm:3.1.0"
   bin:
     jsesc: bin/jsesc
-  checksum: 10c0/dbf59312e0ebf2b4405ef413ec2b25abb5f8f4d9bc5fb8d9f90381622ebca5f2af6a6aa9a8578f65903f9e33990a6dc798edd0ce5586894bf0e9e31803a1de88
+  checksum: 10c0/531779df5ec94f47e462da26b4cbf05eb88a83d9f08aac2ba04206508fc598527a153d08bd462bae82fc78b3eaa1a908e1a4a79f886e9238641c4cdefaf118b1
   languageName: node
   linkType: hard
 
@@ -5468,13 +5349,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"lilconfig@npm:^2.1.0":
-  version: 2.1.0
-  resolution: "lilconfig@npm:2.1.0"
-  checksum: 10c0/64645641aa8d274c99338e130554abd6a0190533c0d9eb2ce7ebfaf2e05c7d9961f3ffe2bfa39efd3b60c521ba3dd24fa236fe2775fc38501bf82bf49d4678b8
-  languageName: node
-  linkType: hard
-
 "lilconfig@npm:^3.0.0":
   version: 3.1.2
   resolution: "lilconfig@npm:3.1.2"
@@ -5482,6 +5356,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"lilconfig@npm:^3.1.3":
+  version: 3.1.3
+  resolution: "lilconfig@npm:3.1.3"
+  checksum: 10c0/f5604e7240c5c275743561442fbc5abf2a84ad94da0f5adc71d25e31fa8483048de3dcedcb7a44112a942fed305fd75841cdf6c9681c7f640c63f1049e9a5dcc
+  languageName: node
+  linkType: hard
+
 "lines-and-columns@npm:^1.1.6":
   version: 1.2.4
   resolution: "lines-and-columns@npm:1.2.4"
@@ -5573,23 +5454,22 @@ __metadata:
   languageName: node
   linkType: hard
 
-"make-fetch-happen@npm:^13.0.0":
-  version: 13.0.1
-  resolution: "make-fetch-happen@npm:13.0.1"
+"make-fetch-happen@npm:^14.0.3":
+  version: 14.0.3
+  resolution: "make-fetch-happen@npm:14.0.3"
   dependencies:
-    "@npmcli/agent": "npm:^2.0.0"
-    cacache: "npm:^18.0.0"
+    "@npmcli/agent": "npm:^3.0.0"
+    cacache: "npm:^19.0.1"
     http-cache-semantics: "npm:^4.1.1"
-    is-lambda: "npm:^1.0.1"
     minipass: "npm:^7.0.2"
-    minipass-fetch: "npm:^3.0.0"
+    minipass-fetch: "npm:^4.0.0"
     minipass-flush: "npm:^1.0.5"
     minipass-pipeline: "npm:^1.2.4"
-    negotiator: "npm:^0.6.3"
-    proc-log: "npm:^4.2.0"
+    negotiator: "npm:^1.0.0"
+    proc-log: "npm:^5.0.0"
     promise-retry: "npm:^2.0.1"
-    ssri: "npm:^10.0.0"
-  checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e
+    ssri: "npm:^12.0.0"
+  checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0
   languageName: node
   linkType: hard
 
@@ -5602,6 +5482,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"math-intrinsics@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "math-intrinsics@npm:1.0.0"
+  checksum: 10c0/470ee2f267b4b3698eb9faa7f0bcf88696d87e2eeab25bba867dc676c09ddbae9b6f2e8ac7a2c1f0c9c2c5299c2a89f4f1f6d0e70d682725e2e7fca7507eef9f
+  languageName: node
+  linkType: hard
+
 "media-typer@npm:0.3.0":
   version: 0.3.0
   resolution: "media-typer@npm:0.3.0"
@@ -5637,7 +5524,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"micromatch@npm:^4.0.4, micromatch@npm:^4.0.5":
+"micromatch@npm:^4.0.4, micromatch@npm:^4.0.8":
   version: 4.0.8
   resolution: "micromatch@npm:4.0.8"
   dependencies:
@@ -5729,18 +5616,18 @@ __metadata:
   languageName: node
   linkType: hard
 
-"minipass-fetch@npm:^3.0.0":
-  version: 3.0.5
-  resolution: "minipass-fetch@npm:3.0.5"
+"minipass-fetch@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "minipass-fetch@npm:4.0.0"
   dependencies:
     encoding: "npm:^0.1.13"
     minipass: "npm:^7.0.3"
     minipass-sized: "npm:^1.0.3"
-    minizlib: "npm:^2.1.2"
+    minizlib: "npm:^3.0.1"
   dependenciesMeta:
     encoding:
       optional: true
-  checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b
+  checksum: 10c0/7fa30ce7c373fb6f94c086b374fff1589fd7e78451855d2d06c2e2d9df936d131e73e952163063016592ed3081444bd8d1ea608533313b0149156ce23311da4b
   languageName: node
   linkType: hard
 
@@ -5780,36 +5667,29 @@ __metadata:
   languageName: node
   linkType: hard
 
-"minipass@npm:^5.0.0":
-  version: 5.0.0
-  resolution: "minipass@npm:5.0.0"
-  checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462
-  languageName: node
-  linkType: hard
-
-"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2":
+"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2":
   version: 7.1.2
   resolution: "minipass@npm:7.1.2"
   checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557
   languageName: node
   linkType: hard
 
-"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2":
-  version: 2.1.2
-  resolution: "minizlib@npm:2.1.2"
+"minizlib@npm:^3.0.1":
+  version: 3.0.1
+  resolution: "minizlib@npm:3.0.1"
   dependencies:
-    minipass: "npm:^3.0.0"
-    yallist: "npm:^4.0.0"
-  checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78
+    minipass: "npm:^7.0.4"
+    rimraf: "npm:^5.0.5"
+  checksum: 10c0/82f8bf70da8af656909a8ee299d7ed3b3372636749d29e105f97f20e88971be31f5ed7642f2e898f00283b68b701cc01307401cdc209b0efc5dd3818220e5093
   languageName: node
   linkType: hard
 
-"mkdirp@npm:^1.0.3":
-  version: 1.0.4
-  resolution: "mkdirp@npm:1.0.4"
+"mkdirp@npm:^3.0.1":
+  version: 3.0.1
+  resolution: "mkdirp@npm:3.0.1"
   bin:
-    mkdirp: bin/cmd.js
-  checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf
+    mkdirp: dist/cjs/src/bin.js
+  checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d
   languageName: node
   linkType: hard
 
@@ -5832,11 +5712,11 @@ __metadata:
   linkType: hard
 
 "nanoid@npm:^3.3.6, nanoid@npm:^3.3.7":
-  version: 3.3.7
-  resolution: "nanoid@npm:3.3.7"
+  version: 3.3.8
+  resolution: "nanoid@npm:3.3.8"
   bin:
     nanoid: bin/nanoid.cjs
-  checksum: 10c0/e3fb661aa083454f40500473bb69eedb85dc160e763150b9a2c567c7e9ff560ce028a9f833123b618a6ea742e311138b591910e795614a629029e86e180660f3
+  checksum: 10c0/4b1bb29f6cfebf3be3bc4ad1f1296fb0a10a3043a79f34fbffe75d1621b4318319211cd420549459018ea3592f0d2f159247a6f874911d6d26eaaadda2478120
   languageName: node
   linkType: hard
 
@@ -5847,24 +5727,31 @@ __metadata:
   languageName: node
   linkType: hard
 
-"negotiator@npm:0.6.3, negotiator@npm:^0.6.3":
+"negotiator@npm:0.6.3":
   version: 0.6.3
   resolution: "negotiator@npm:0.6.3"
   checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2
   languageName: node
   linkType: hard
 
+"negotiator@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "negotiator@npm:1.0.0"
+  checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b
+  languageName: node
+  linkType: hard
+
 "next-intl@npm:^3.19.1":
-  version: 3.19.4
-  resolution: "next-intl@npm:3.19.4"
+  version: 3.26.1
+  resolution: "next-intl@npm:3.26.1"
   dependencies:
     "@formatjs/intl-localematcher": "npm:^0.5.4"
-    negotiator: "npm:^0.6.3"
-    use-intl: "npm:^3.19.4"
+    negotiator: "npm:^1.0.0"
+    use-intl: "npm:^3.26.1"
   peerDependencies:
-    next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0
-    react: ^16.8.0 || ^17.0.0 || ^18.0.0
-  checksum: 10c0/a8dd185b9d290903eed8b63c55490842dcda969c591553d4994fcacce647e8a3816e73edeb61cb098c73e89e303501c077e2efdad953e2f5c7e786f3edc058c0
+    next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
+    react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
+  checksum: 10c0/dfb67e132d62feda76be6d84ed8100edcbad2599b1cc355a2f854cdd5ab6722d767585f7dce79c759aca27dadef5b9a3273dedff6bb12d397409cfd15cc5cd78
   languageName: node
   linkType: hard
 
@@ -5938,22 +5825,22 @@ __metadata:
   linkType: hard
 
 "node-gyp@npm:latest":
-  version: 10.2.0
-  resolution: "node-gyp@npm:10.2.0"
+  version: 11.0.0
+  resolution: "node-gyp@npm:11.0.0"
   dependencies:
     env-paths: "npm:^2.2.0"
     exponential-backoff: "npm:^3.1.1"
     glob: "npm:^10.3.10"
     graceful-fs: "npm:^4.2.6"
-    make-fetch-happen: "npm:^13.0.0"
-    nopt: "npm:^7.0.0"
-    proc-log: "npm:^4.1.0"
+    make-fetch-happen: "npm:^14.0.3"
+    nopt: "npm:^8.0.0"
+    proc-log: "npm:^5.0.0"
     semver: "npm:^7.3.5"
-    tar: "npm:^6.2.1"
-    which: "npm:^4.0.0"
+    tar: "npm:^7.4.3"
+    which: "npm:^5.0.0"
   bin:
     node-gyp: bin/node-gyp.js
-  checksum: 10c0/00630d67dbd09a45aee0a5d55c05e3916ca9e6d427ee4f7bc392d2d3dc5fad7449b21fc098dd38260a53d9dcc9c879b36704a1994235d4707e7271af7e9a835b
+  checksum: 10c0/a3b885bbee2d271f1def32ba2e30ffcf4562a3db33af06b8b365e053153e2dd2051b9945783c3c8e852d26a0f20f65b251c7e83361623383a99635c0280ee573
   languageName: node
   linkType: hard
 
@@ -5965,11 +5852,9 @@ __metadata:
   linkType: hard
 
 "node-mocks-http@npm:^1.14.1":
-  version: 1.16.0
-  resolution: "node-mocks-http@npm:1.16.0"
+  version: 1.16.2
+  resolution: "node-mocks-http@npm:1.16.2"
   dependencies:
-    "@types/express": "npm:^4.17.21"
-    "@types/node": "npm:*"
     accepts: "npm:^1.3.7"
     content-disposition: "npm:^0.5.3"
     depd: "npm:^1.1.0"
@@ -5980,25 +5865,33 @@ __metadata:
     parseurl: "npm:^1.3.3"
     range-parser: "npm:^1.2.0"
     type-is: "npm:^1.6.18"
-  checksum: 10c0/b48e6c9115912790963a833e7e29d20f42e87d1ec33f76bf81c000e90246db720f9051f4adbd5aa3fa863b3f5fca090e0fd4463060064845e8e34b6b38a966d7
+  peerDependencies:
+    "@types/express": ^4.17.21 || ^5.0.0
+    "@types/node": "*"
+  peerDependenciesMeta:
+    "@types/express":
+      optional: true
+    "@types/node":
+      optional: true
+  checksum: 10c0/0d94f2c179a2a9b42c042d554faaed348083213400e9da0b0b25ce4498eb4f4d9467550402f53b2e5d1f1bbf5444c7d6c232ca377b56e5af9fbde9c9d85ad8fa
   languageName: node
   linkType: hard
 
 "node-releases@npm:^2.0.18":
-  version: 2.0.18
-  resolution: "node-releases@npm:2.0.18"
-  checksum: 10c0/786ac9db9d7226339e1dc84bbb42007cb054a346bd9257e6aa154d294f01bc6a6cddb1348fa099f079be6580acbb470e3c048effd5f719325abd0179e566fd27
+  version: 2.0.19
+  resolution: "node-releases@npm:2.0.19"
+  checksum: 10c0/52a0dbd25ccf545892670d1551690fe0facb6a471e15f2cfa1b20142a5b255b3aa254af5f59d6ecb69c2bec7390bc643c43aa63b13bf5e64b6075952e716b1aa
   languageName: node
   linkType: hard
 
-"nopt@npm:^7.0.0":
-  version: 7.2.1
-  resolution: "nopt@npm:7.2.1"
+"nopt@npm:^8.0.0":
+  version: 8.0.0
+  resolution: "nopt@npm:8.0.0"
   dependencies:
     abbrev: "npm:^2.0.0"
   bin:
     nopt: bin/nopt.js
-  checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81
+  checksum: 10c0/19cb986f79abaca2d0f0b560021da7b32ee6fcc3de48f3eaeb0c324d36755c17754f886a754c091f01f740c17caf7d6aea8237b7fbaf39f476ae5e30a249f18f
   languageName: node
   linkType: hard
 
@@ -6026,9 +5919,9 @@ __metadata:
   linkType: hard
 
 "nwsapi@npm:^2.2.2":
-  version: 2.2.12
-  resolution: "nwsapi@npm:2.2.12"
-  checksum: 10c0/95e9623d63df111405503df8c5d800e26f71675d319e2c9c70cddfa31e5ace1d3f8b6d98d354544fc156a1506d920ec291e303fab761e4f99296868e199a466e
+  version: 2.2.16
+  resolution: "nwsapi@npm:2.2.16"
+  checksum: 10c0/0aa0637f4d51043d0183d994e08336bae996b03b42984381bf09ebdf3ff4909c018eda6b2a8aba0a08f3ea8303db8a0dad0608b38dc0bff15fd87017286ae21a
   languageName: node
   linkType: hard
 
@@ -6046,10 +5939,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"object-inspect@npm:^1.13.1":
-  version: 1.13.2
-  resolution: "object-inspect@npm:1.13.2"
-  checksum: 10c0/b97835b4c91ec37b5fd71add84f21c3f1047d1d155d00c0fcd6699516c256d4fcc6ff17a1aced873197fe447f91a3964178fd2a67a1ee2120cdaf60e81a050b4
+"object-inspect@npm:^1.13.3":
+  version: 1.13.3
+  resolution: "object-inspect@npm:1.13.3"
+  checksum: 10c0/cc3f15213406be89ffdc54b525e115156086796a515410a8d390215915db9f23c8eab485a06f1297402f440a33715fe8f71a528c1dcbad6e1a3bcaf5a46921d4
   languageName: node
   linkType: hard
 
@@ -6195,12 +6088,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"p-map@npm:^4.0.0":
-  version: 4.0.0
-  resolution: "p-map@npm:4.0.0"
-  dependencies:
-    aggregate-error: "npm:^3.0.0"
-  checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75
+"p-map@npm:^7.0.2":
+  version: 7.0.3
+  resolution: "p-map@npm:7.0.3"
+  checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c
   languageName: node
   linkType: hard
 
@@ -6212,9 +6103,9 @@ __metadata:
   linkType: hard
 
 "package-json-from-dist@npm:^1.0.0":
-  version: 1.0.0
-  resolution: "package-json-from-dist@npm:1.0.0"
-  checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033
+  version: 1.0.1
+  resolution: "package-json-from-dist@npm:1.0.1"
+  checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b
   languageName: node
   linkType: hard
 
@@ -6240,11 +6131,11 @@ __metadata:
   linkType: hard
 
 "parse5@npm:^7.0.0, parse5@npm:^7.1.1":
-  version: 7.1.2
-  resolution: "parse5@npm:7.1.2"
+  version: 7.2.1
+  resolution: "parse5@npm:7.2.1"
   dependencies:
-    entities: "npm:^4.4.0"
-  checksum: 10c0/297d7af8224f4b5cb7f6617ecdae98eeaed7f8cbd78956c42785e230505d5a4f07cef352af10d3006fa5c1544b76b57784d3a22d861ae071bbc460c649482bf4
+    entities: "npm:^4.5.0"
+  checksum: 10c0/829d37a0c709215a887e410a7118d754f8e1afd7edb529db95bc7bbf8045fb0266a7b67801331d8e8d9d073ea75793624ec27ce9ff3b96862c3b9008f4d68e80
   languageName: node
   linkType: hard
 
@@ -6300,10 +6191,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1, picocolors@npm:^1.1.0":
-  version: 1.1.0
-  resolution: "picocolors@npm:1.1.0"
-  checksum: 10c0/86946f6032148801ef09c051c6fb13b5cf942eaf147e30ea79edb91dd32d700934edebe782a1078ff859fb2b816792e97ef4dab03d7f0b804f6b01a0df35e023
+"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1":
+  version: 1.1.1
+  resolution: "picocolors@npm:1.1.1"
+  checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58
   languageName: node
   linkType: hard
 
@@ -6368,7 +6259,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-load-config@npm:^4.0.1":
+"postcss-load-config@npm:^4.0.2":
   version: 4.0.2
   resolution: "postcss-load-config@npm:4.0.2"
   dependencies:
@@ -6386,7 +6277,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-nested@npm:^6.0.1":
+"postcss-nested@npm:^6.2.0":
   version: 6.2.0
   resolution: "postcss-nested@npm:6.2.0"
   dependencies:
@@ -6397,7 +6288,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.1.1":
+"postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2":
   version: 6.1.2
   resolution: "postcss-selector-parser@npm:6.1.2"
   dependencies:
@@ -6414,7 +6305,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss@npm:8.4.31":
+"postcss@npm:8.4.31, postcss@npm:^8":
   version: 8.4.31
   resolution: "postcss@npm:8.4.31"
   dependencies:
@@ -6425,14 +6316,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss@npm:^8, postcss@npm:^8.4.23":
-  version: 8.4.47
-  resolution: "postcss@npm:8.4.47"
+"postcss@npm:^8.4.47":
+  version: 8.4.49
+  resolution: "postcss@npm:8.4.49"
   dependencies:
     nanoid: "npm:^3.3.7"
-    picocolors: "npm:^1.1.0"
+    picocolors: "npm:^1.1.1"
     source-map-js: "npm:^1.2.1"
-  checksum: 10c0/929f68b5081b7202709456532cee2a145c1843d391508c5a09de2517e8c4791638f71dd63b1898dba6712f8839d7a6da046c72a5e44c162e908f5911f57b5f44
+  checksum: 10c0/f1b3f17aaf36d136f59ec373459f18129908235e65dbdc3aee5eef8eba0756106f52de5ec4682e29a2eab53eb25170e7e871b3e4b52a8f1de3d344a514306be3
   languageName: node
   linkType: hard
 
@@ -6453,11 +6344,11 @@ __metadata:
   linkType: hard
 
 "prettier@npm:^3.2.5":
-  version: 3.3.3
-  resolution: "prettier@npm:3.3.3"
+  version: 3.4.2
+  resolution: "prettier@npm:3.4.2"
   bin:
     prettier: bin/prettier.cjs
-  checksum: 10c0/b85828b08e7505716324e4245549b9205c0cacb25342a030ba8885aba2039a115dbcf75a0b7ca3b37bc9d101ee61fab8113fc69ca3359f2a226f1ecc07ad2e26
+  checksum: 10c0/99e076a26ed0aba4ebc043880d0f08bbb8c59a4c6641cdee6cdadf2205bdd87aa1d7823f50c3aea41e015e99878d37c58d7b5f0e663bba0ef047f94e36b96446
   languageName: node
   linkType: hard
 
@@ -6483,10 +6374,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0":
-  version: 4.2.0
-  resolution: "proc-log@npm:4.2.0"
-  checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9
+"proc-log@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "proc-log@npm:5.0.0"
+  checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3
   languageName: node
   linkType: hard
 
@@ -6522,13 +6413,15 @@ __metadata:
   linkType: hard
 
 "psl@npm:^1.1.33":
-  version: 1.9.0
-  resolution: "psl@npm:1.9.0"
-  checksum: 10c0/6a3f805fdab9442f44de4ba23880c4eba26b20c8e8e0830eff1cb31007f6825dace61d17203c58bfe36946842140c97a1ba7f67bc63ca2d88a7ee052b65d97ab
+  version: 1.15.0
+  resolution: "psl@npm:1.15.0"
+  dependencies:
+    punycode: "npm:^2.3.1"
+  checksum: 10c0/d8d45a99e4ca62ca12ac3c373e63d80d2368d38892daa40cfddaa1eb908be98cd549ac059783ef3a56cfd96d57ae8e2fd9ae53d1378d90d42bc661ff924e102a
   languageName: node
   linkType: hard
 
-"punycode@npm:^2.1.0, punycode@npm:^2.1.1":
+"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1":
   version: 2.3.1
   resolution: "punycode@npm:2.3.1"
   checksum: 10c0/14f76a8206bc3464f794fb2e3d3cc665ae416c01893ad7a02b23766eb07159144ee612ad67af5e84fa4479ccfe67678c4feb126b0485651b302babf66f04f9e9
@@ -6644,18 +6537,19 @@ __metadata:
   languageName: node
   linkType: hard
 
-"reflect.getprototypeof@npm:^1.0.4":
-  version: 1.0.6
-  resolution: "reflect.getprototypeof@npm:1.0.6"
+"reflect.getprototypeof@npm:^1.0.6, reflect.getprototypeof@npm:^1.0.8":
+  version: 1.0.8
+  resolution: "reflect.getprototypeof@npm:1.0.8"
   dependencies:
-    call-bind: "npm:^1.0.7"
+    call-bind: "npm:^1.0.8"
     define-properties: "npm:^1.2.1"
-    es-abstract: "npm:^1.23.1"
+    dunder-proto: "npm:^1.0.0"
+    es-abstract: "npm:^1.23.5"
     es-errors: "npm:^1.3.0"
     get-intrinsic: "npm:^1.2.4"
-    globalthis: "npm:^1.0.3"
-    which-builtin-type: "npm:^1.1.3"
-  checksum: 10c0/baf4ef8ee6ff341600f4720b251cf5a6cb552d6a6ab0fdc036988c451bf16f920e5feb0d46bd4f530a5cce568f1f7aca2d77447ca798920749cfc52783c39b55
+    gopd: "npm:^1.2.0"
+    which-builtin-type: "npm:^1.2.0"
+  checksum: 10c0/720479dd7a72a20d66efaca507ed7c7e18403d24ce764f436130464d4a516a12ed8a9a2714dcabc3e1296f9a31f914ba1095e2371619df23d3ac56c4f8c8bae1
   languageName: node
   linkType: hard
 
@@ -6666,15 +6560,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2":
-  version: 1.5.2
-  resolution: "regexp.prototype.flags@npm:1.5.2"
+"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2, regexp.prototype.flags@npm:^1.5.3":
+  version: 1.5.3
+  resolution: "regexp.prototype.flags@npm:1.5.3"
   dependencies:
-    call-bind: "npm:^1.0.6"
+    call-bind: "npm:^1.0.7"
     define-properties: "npm:^1.2.1"
     es-errors: "npm:^1.3.0"
-    set-function-name: "npm:^2.0.1"
-  checksum: 10c0/0f3fc4f580d9c349f8b560b012725eb9c002f36daa0041b3fbf6f4238cb05932191a4d7d5db3b5e2caa336d5150ad0402ed2be81f711f9308fe7e1a9bf9bd552
+    set-function-name: "npm:^2.0.2"
+  checksum: 10c0/e1a7c7dc42cc91abf73e47a269c4b3a8f225321b7f617baa25821f6a123a91d23a73b5152f21872c566e699207e1135d075d2251cd3e84cc96d82a910adf6020
   languageName: node
   linkType: hard
 
@@ -6737,13 +6631,13 @@ __metadata:
   linkType: hard
 
 "resolve.exports@npm:^2.0.0":
-  version: 2.0.2
-  resolution: "resolve.exports@npm:2.0.2"
-  checksum: 10c0/cc4cffdc25447cf34730f388dca5021156ba9302a3bad3d7f168e790dc74b2827dff603f1bc6ad3d299bac269828dca96dd77e036dc9fba6a2a1807c47ab5c98
+  version: 2.0.3
+  resolution: "resolve.exports@npm:2.0.3"
+  checksum: 10c0/1ade1493f4642a6267d0a5e68faeac20b3d220f18c28b140343feb83694d8fed7a286852aef43689d16042c61e2ddb270be6578ad4a13990769e12065191200d
   languageName: node
   linkType: hard
 
-"resolve@npm:^1.1.7, resolve@npm:^1.10.1, resolve@npm:^1.20.0, resolve@npm:^1.22.2, resolve@npm:^1.22.4":
+"resolve@npm:^1.1.7, resolve@npm:^1.10.1, resolve@npm:^1.20.0, resolve@npm:^1.22.4, resolve@npm:^1.22.8":
   version: 1.22.8
   resolution: "resolve@npm:1.22.8"
   dependencies:
@@ -6769,7 +6663,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin<compat/resolve>":
+"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin<compat/resolve>":
   version: 1.22.8
   resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin<compat/resolve>::version=1.22.8&hash=c3c19d"
   dependencies:
@@ -6820,6 +6714,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"rimraf@npm:^5.0.5":
+  version: 5.0.10
+  resolution: "rimraf@npm:5.0.10"
+  dependencies:
+    glob: "npm:^10.3.7"
+  bin:
+    rimraf: dist/esm/bin.mjs
+  checksum: 10c0/7da4fd0e15118ee05b918359462cfa1e7fe4b1228c7765195a45b55576e8c15b95db513b8466ec89129666f4af45ad978a3057a02139afba1a63512a2d9644cc
+  languageName: node
+  linkType: hard
+
 "run-parallel@npm:^1.1.9":
   version: 1.2.0
   resolution: "run-parallel@npm:1.2.0"
@@ -6830,14 +6735,15 @@ __metadata:
   linkType: hard
 
 "safe-array-concat@npm:^1.1.2":
-  version: 1.1.2
-  resolution: "safe-array-concat@npm:1.1.2"
+  version: 1.1.3
+  resolution: "safe-array-concat@npm:1.1.3"
   dependencies:
-    call-bind: "npm:^1.0.7"
-    get-intrinsic: "npm:^1.2.4"
-    has-symbols: "npm:^1.0.3"
+    call-bind: "npm:^1.0.8"
+    call-bound: "npm:^1.0.2"
+    get-intrinsic: "npm:^1.2.6"
+    has-symbols: "npm:^1.1.0"
     isarray: "npm:^2.0.5"
-  checksum: 10c0/12f9fdb01c8585e199a347eacc3bae7b5164ae805cdc8c6707199dbad5b9e30001a50a43c4ee24dc9ea32dbb7279397850e9208a7e217f4d8b1cf5d90129dec9
+  checksum: 10c0/43c86ffdddc461fb17ff8a17c5324f392f4868f3c7dd2c6a5d9f5971713bc5fd755667212c80eab9567595f9a7509cc2f83e590ddaebd1bd19b780f9c79f9a8d
   languageName: node
   linkType: hard
 
@@ -6848,14 +6754,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"safe-regex-test@npm:^1.0.3":
-  version: 1.0.3
-  resolution: "safe-regex-test@npm:1.0.3"
+"safe-regex-test@npm:^1.0.3, safe-regex-test@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "safe-regex-test@npm:1.1.0"
   dependencies:
-    call-bind: "npm:^1.0.6"
+    call-bound: "npm:^1.0.2"
     es-errors: "npm:^1.3.0"
-    is-regex: "npm:^1.1.4"
-  checksum: 10c0/900bf7c98dc58f08d8523b7012b468e4eb757afa624f198902c0643d7008ba777b0bdc35810ba0b758671ce887617295fb742b3f3968991b178ceca54cb07603
+    is-regex: "npm:^1.2.1"
+  checksum: 10c0/f2c25281bbe5d39cddbbce7f86fca5ea9b3ce3354ea6cd7c81c31b006a5a9fff4286acc5450a3b9122c56c33eba69c56b9131ad751457b2b4a585825e6a10665
   languageName: node
   linkType: hard
 
@@ -6902,7 +6808,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"set-function-length@npm:^1.2.1":
+"set-function-length@npm:^1.2.2":
   version: 1.2.2
   resolution: "set-function-length@npm:1.2.2"
   dependencies:
@@ -6916,7 +6822,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"set-function-name@npm:^2.0.1, set-function-name@npm:^2.0.2":
+"set-function-name@npm:^2.0.2":
   version: 2.0.2
   resolution: "set-function-name@npm:2.0.2"
   dependencies:
@@ -7013,15 +6919,51 @@ __metadata:
   languageName: node
   linkType: hard
 
+"side-channel-list@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "side-channel-list@npm:1.0.0"
+  dependencies:
+    es-errors: "npm:^1.3.0"
+    object-inspect: "npm:^1.13.3"
+  checksum: 10c0/644f4ac893456c9490ff388bf78aea9d333d5e5bfc64cfb84be8f04bf31ddc111a8d4b83b85d7e7e8a7b845bc185a9ad02c052d20e086983cf59f0be517d9b3d
+  languageName: node
+  linkType: hard
+
+"side-channel-map@npm:^1.0.1":
+  version: 1.0.1
+  resolution: "side-channel-map@npm:1.0.1"
+  dependencies:
+    call-bound: "npm:^1.0.2"
+    es-errors: "npm:^1.3.0"
+    get-intrinsic: "npm:^1.2.5"
+    object-inspect: "npm:^1.13.3"
+  checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672
+  languageName: node
+  linkType: hard
+
+"side-channel-weakmap@npm:^1.0.2":
+  version: 1.0.2
+  resolution: "side-channel-weakmap@npm:1.0.2"
+  dependencies:
+    call-bound: "npm:^1.0.2"
+    es-errors: "npm:^1.3.0"
+    get-intrinsic: "npm:^1.2.5"
+    object-inspect: "npm:^1.13.3"
+    side-channel-map: "npm:^1.0.1"
+  checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185
+  languageName: node
+  linkType: hard
+
 "side-channel@npm:^1.0.4, side-channel@npm:^1.0.6":
-  version: 1.0.6
-  resolution: "side-channel@npm:1.0.6"
+  version: 1.1.0
+  resolution: "side-channel@npm:1.1.0"
   dependencies:
-    call-bind: "npm:^1.0.7"
     es-errors: "npm:^1.3.0"
-    get-intrinsic: "npm:^1.2.4"
-    object-inspect: "npm:^1.13.1"
-  checksum: 10c0/d2afd163dc733cc0a39aa6f7e39bf0c436293510dbccbff446733daeaf295857dbccf94297092ec8c53e2503acac30f0b78830876f0485991d62a90e9cad305f
+    object-inspect: "npm:^1.13.3"
+    side-channel-list: "npm:^1.0.0"
+    side-channel-map: "npm:^1.0.1"
+    side-channel-weakmap: "npm:^1.0.2"
+  checksum: 10c0/cb20dad41eb032e6c24c0982e1e5a24963a28aa6122b4f05b3f3d6bf8ae7fd5474ef382c8f54a6a3ab86e0cac4d41a23bd64ede3970e5bfb50326ba02a7996e6
   languageName: node
   linkType: hard
 
@@ -7070,13 +7012,13 @@ __metadata:
   linkType: hard
 
 "socks-proxy-agent@npm:^8.0.3":
-  version: 8.0.4
-  resolution: "socks-proxy-agent@npm:8.0.4"
+  version: 8.0.5
+  resolution: "socks-proxy-agent@npm:8.0.5"
   dependencies:
-    agent-base: "npm:^7.1.1"
+    agent-base: "npm:^7.1.2"
     debug: "npm:^4.3.4"
     socks: "npm:^2.8.3"
-  checksum: 10c0/345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a
+  checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6
   languageName: node
   linkType: hard
 
@@ -7128,12 +7070,19 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ssri@npm:^10.0.0":
-  version: 10.0.6
-  resolution: "ssri@npm:10.0.6"
+"ssri@npm:^12.0.0":
+  version: 12.0.0
+  resolution: "ssri@npm:12.0.0"
   dependencies:
     minipass: "npm:^7.0.3"
-  checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227
+  checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d
+  languageName: node
+  linkType: hard
+
+"stable-hash@npm:^0.0.4":
+  version: 0.0.4
+  resolution: "stable-hash@npm:0.0.4"
+  checksum: 10c0/53d010d2a1b014fb60d398c095f43912c353b7b44774e55222bb26fd428bc75b73d7bdfcae509ce927c23ca9c5aff2dc1bc82f191d30e57a879550bc2952bdb0
   languageName: node
   linkType: hard
 
@@ -7194,13 +7143,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"string.prototype.includes@npm:^2.0.0":
-  version: 2.0.0
-  resolution: "string.prototype.includes@npm:2.0.0"
+"string.prototype.includes@npm:^2.0.1":
+  version: 2.0.1
+  resolution: "string.prototype.includes@npm:2.0.1"
   dependencies:
-    define-properties: "npm:^1.1.3"
-    es-abstract: "npm:^1.17.5"
-  checksum: 10c0/32dff118c9e9dcc87e240b05462fa8ee7248d9e335c0015c1442fe18152261508a2146d9bb87ddae56abab69148a83c61dfaea33f53853812a6a2db737689ed2
+    call-bind: "npm:^1.0.7"
+    define-properties: "npm:^1.2.1"
+    es-abstract: "npm:^1.23.3"
+  checksum: 10c0/25ce9c9b49128352a2618fbe8758b46f945817a58a4420f4799419e40a8d28f116e176c7590d767d5327a61e75c8f32c86171063f48e389b9fdd325f1bd04ee5
   languageName: node
   linkType: hard
 
@@ -7235,25 +7185,29 @@ __metadata:
   linkType: hard
 
 "string.prototype.trim@npm:^1.2.9":
-  version: 1.2.9
-  resolution: "string.prototype.trim@npm:1.2.9"
+  version: 1.2.10
+  resolution: "string.prototype.trim@npm:1.2.10"
   dependencies:
-    call-bind: "npm:^1.0.7"
+    call-bind: "npm:^1.0.8"
+    call-bound: "npm:^1.0.2"
+    define-data-property: "npm:^1.1.4"
     define-properties: "npm:^1.2.1"
-    es-abstract: "npm:^1.23.0"
+    es-abstract: "npm:^1.23.5"
     es-object-atoms: "npm:^1.0.0"
-  checksum: 10c0/dcef1a0fb61d255778155006b372dff8cc6c4394bc39869117e4241f41a2c52899c0d263ffc7738a1f9e61488c490b05c0427faa15151efad721e1a9fb2663c2
+    has-property-descriptors: "npm:^1.0.2"
+  checksum: 10c0/8a8854241c4b54a948e992eb7dd6b8b3a97185112deb0037a134f5ba57541d8248dd610c966311887b6c2fd1181a3877bffb14d873ce937a344535dabcc648f8
   languageName: node
   linkType: hard
 
 "string.prototype.trimend@npm:^1.0.8":
-  version: 1.0.8
-  resolution: "string.prototype.trimend@npm:1.0.8"
+  version: 1.0.9
+  resolution: "string.prototype.trimend@npm:1.0.9"
   dependencies:
-    call-bind: "npm:^1.0.7"
+    call-bind: "npm:^1.0.8"
+    call-bound: "npm:^1.0.2"
     define-properties: "npm:^1.2.1"
     es-object-atoms: "npm:^1.0.0"
-  checksum: 10c0/0a0b54c17c070551b38e756ae271865ac6cc5f60dabf2e7e343cceae7d9b02e1a1120a824e090e79da1b041a74464e8477e2da43e2775c85392be30a6f60963c
+  checksum: 10c0/59e1a70bf9414cb4c536a6e31bef5553c8ceb0cf44d8b4d0ed65c9653358d1c64dd0ec203b100df83d0413bbcde38b8c5d49e14bc4b86737d74adc593a0d35b6
   languageName: node
   linkType: hard
 
@@ -7339,7 +7293,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"sucrase@npm:^3.32.0":
+"sucrase@npm:^3.35.0":
   version: 3.35.0
   resolution: "sucrase@npm:3.35.0"
   dependencies:
@@ -7357,15 +7311,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"supports-color@npm:^5.3.0":
-  version: 5.5.0
-  resolution: "supports-color@npm:5.5.0"
-  dependencies:
-    has-flag: "npm:^3.0.0"
-  checksum: 10c0/6ae5ff319bfbb021f8a86da8ea1f8db52fac8bd4d499492e30ec17095b58af11f0c55f8577390a749b1c4dde691b6a0315dab78f5f54c9b3d83f8fb5905c1c05
-  languageName: node
-  linkType: hard
-
 "supports-color@npm:^7.1.0":
   version: 7.2.0
   resolution: "supports-color@npm:7.2.0"
@@ -7399,45 +7344,45 @@ __metadata:
   linkType: hard
 
 "synckit@npm:^0.9.1":
-  version: 0.9.1
-  resolution: "synckit@npm:0.9.1"
+  version: 0.9.2
+  resolution: "synckit@npm:0.9.2"
   dependencies:
     "@pkgr/core": "npm:^0.1.0"
     tslib: "npm:^2.6.2"
-  checksum: 10c0/d8b89e1bf30ba3ffb469d8418c836ad9c0c062bf47028406b4d06548bc66af97155ea2303b96c93bf5c7c0f0d66153a6fbd6924c76521b434e6a9898982abc2e
+  checksum: 10c0/e0c262817444e5b872708adb6f5ad37951ba33f6b2d1d4477d45db1f57573a784618ceed5e6614e0225db330632b1f6b95bb74d21e4d013e45ad4bde03d0cb59
   languageName: node
   linkType: hard
 
 "tailwindcss@npm:^3.3.0":
-  version: 3.4.12
-  resolution: "tailwindcss@npm:3.4.12"
+  version: 3.4.16
+  resolution: "tailwindcss@npm:3.4.16"
   dependencies:
     "@alloc/quick-lru": "npm:^5.2.0"
     arg: "npm:^5.0.2"
-    chokidar: "npm:^3.5.3"
+    chokidar: "npm:^3.6.0"
     didyoumean: "npm:^1.2.2"
     dlv: "npm:^1.1.3"
-    fast-glob: "npm:^3.3.0"
+    fast-glob: "npm:^3.3.2"
     glob-parent: "npm:^6.0.2"
     is-glob: "npm:^4.0.3"
-    jiti: "npm:^1.21.0"
-    lilconfig: "npm:^2.1.0"
-    micromatch: "npm:^4.0.5"
+    jiti: "npm:^1.21.6"
+    lilconfig: "npm:^3.1.3"
+    micromatch: "npm:^4.0.8"
     normalize-path: "npm:^3.0.0"
     object-hash: "npm:^3.0.0"
-    picocolors: "npm:^1.0.0"
-    postcss: "npm:^8.4.23"
+    picocolors: "npm:^1.1.1"
+    postcss: "npm:^8.4.47"
     postcss-import: "npm:^15.1.0"
     postcss-js: "npm:^4.0.1"
-    postcss-load-config: "npm:^4.0.1"
-    postcss-nested: "npm:^6.0.1"
-    postcss-selector-parser: "npm:^6.0.11"
-    resolve: "npm:^1.22.2"
-    sucrase: "npm:^3.32.0"
+    postcss-load-config: "npm:^4.0.2"
+    postcss-nested: "npm:^6.2.0"
+    postcss-selector-parser: "npm:^6.1.2"
+    resolve: "npm:^1.22.8"
+    sucrase: "npm:^3.35.0"
   bin:
     tailwind: lib/cli.js
     tailwindcss: lib/cli.js
-  checksum: 10c0/9ed1449d3b98ce54c6c3a6c3354121a14b39d8dba28815ea1b0fc5a0b32422a744545ba357690468912a1a781593bc7da3d4e56367abed284a300ae1fb0ab42b
+  checksum: 10c0/f716ff38e0ea6f25c2b3d811e0aaac07f627193e8527d8ad945d5088d4a188ac1eb1e8ee9aef76d8525e756ffbb8369d717013d3ffc2f49fabaa94cb1e6784c1
   languageName: node
   linkType: hard
 
@@ -7448,17 +7393,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"tar@npm:^6.1.11, tar@npm:^6.2.1":
-  version: 6.2.1
-  resolution: "tar@npm:6.2.1"
+"tar@npm:^7.4.3":
+  version: 7.4.3
+  resolution: "tar@npm:7.4.3"
   dependencies:
-    chownr: "npm:^2.0.0"
-    fs-minipass: "npm:^2.0.0"
-    minipass: "npm:^5.0.0"
-    minizlib: "npm:^2.1.1"
-    mkdirp: "npm:^1.0.3"
-    yallist: "npm:^4.0.0"
-  checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537
+    "@isaacs/fs-minipass": "npm:^4.0.0"
+    chownr: "npm:^3.0.0"
+    minipass: "npm:^7.1.2"
+    minizlib: "npm:^3.0.1"
+    mkdirp: "npm:^3.0.1"
+    yallist: "npm:^5.0.0"
+  checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d
   languageName: node
   linkType: hard
 
@@ -7512,13 +7457,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"to-fast-properties@npm:^2.0.0":
-  version: 2.0.0
-  resolution: "to-fast-properties@npm:2.0.0"
-  checksum: 10c0/b214d21dbfb4bce3452b6244b336806ffea9c05297148d32ebb428d5c43ce7545bdfc65a1ceb58c9ef4376a65c0cb2854d645f33961658b3e3b4f84910ddcdd7
-  languageName: node
-  linkType: hard
-
 "to-regex-range@npm:^5.0.1":
   version: 5.0.1
   resolution: "to-regex-range@npm:5.0.1"
@@ -7557,11 +7495,11 @@ __metadata:
   linkType: hard
 
 "ts-api-utils@npm:^1.0.1":
-  version: 1.3.0
-  resolution: "ts-api-utils@npm:1.3.0"
+  version: 1.4.3
+  resolution: "ts-api-utils@npm:1.4.3"
   peerDependencies:
     typescript: ">=4.2.0"
-  checksum: 10c0/f54a0ba9ed56ce66baea90a3fa087a484002e807f28a8ccb2d070c75e76bde64bd0f6dce98b3802834156306050871b67eec325cb4e918015a360a3f0868c77c
+  checksum: 10c0/e65dc6e7e8141140c23e1dc94984bf995d4f6801919c71d6dc27cf0cd51b100a91ffcfe5217626193e5bea9d46831e8586febdc7e172df3f1091a7384299e23a
   languageName: node
   linkType: hard
 
@@ -7622,10 +7560,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"tslib@npm:^2.4.0, tslib@npm:^2.6.2":
-  version: 2.7.0
-  resolution: "tslib@npm:2.7.0"
-  checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6
+"tslib@npm:2, tslib@npm:^2.4.0, tslib@npm:^2.6.2":
+  version: 2.8.1
+  resolution: "tslib@npm:2.8.1"
+  checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
   languageName: node
   linkType: hard
 
@@ -7694,8 +7632,8 @@ __metadata:
   linkType: hard
 
 "typed-array-byte-offset@npm:^1.0.2":
-  version: 1.0.2
-  resolution: "typed-array-byte-offset@npm:1.0.2"
+  version: 1.0.3
+  resolution: "typed-array-byte-offset@npm:1.0.3"
   dependencies:
     available-typed-arrays: "npm:^1.0.7"
     call-bind: "npm:^1.0.7"
@@ -7703,41 +7641,42 @@ __metadata:
     gopd: "npm:^1.0.1"
     has-proto: "npm:^1.0.3"
     is-typed-array: "npm:^1.1.13"
-  checksum: 10c0/d2628bc739732072e39269389a758025f75339de2ed40c4f91357023c5512d237f255b633e3106c461ced41907c1bf9a533c7e8578066b0163690ca8bc61b22f
+    reflect.getprototypeof: "npm:^1.0.6"
+  checksum: 10c0/5da29585f96671c0521475226d3227000b3e01d1e99208b66bb05b75c7c8f4d0e9cc2e79920f3bfbc792a00102df1daa2608a2753e3f291b671d5a80245bde5b
   languageName: node
   linkType: hard
 
 "typed-array-length@npm:^1.0.6":
-  version: 1.0.6
-  resolution: "typed-array-length@npm:1.0.6"
+  version: 1.0.7
+  resolution: "typed-array-length@npm:1.0.7"
   dependencies:
     call-bind: "npm:^1.0.7"
     for-each: "npm:^0.3.3"
     gopd: "npm:^1.0.1"
-    has-proto: "npm:^1.0.3"
     is-typed-array: "npm:^1.1.13"
     possible-typed-array-names: "npm:^1.0.0"
-  checksum: 10c0/74253d7dc488eb28b6b2711cf31f5a9dcefc9c41b0681fd1c178ed0a1681b4468581a3626d39cd4df7aee3d3927ab62be06aa9ca74e5baf81827f61641445b77
+    reflect.getprototypeof: "npm:^1.0.6"
+  checksum: 10c0/e38f2ae3779584c138a2d8adfa8ecf749f494af3cd3cdafe4e688ce51418c7d2c5c88df1bd6be2bbea099c3f7cea58c02ca02ed438119e91f162a9de23f61295
   languageName: node
   linkType: hard
 
 "typescript@npm:^5":
-  version: 5.6.2
-  resolution: "typescript@npm:5.6.2"
+  version: 5.7.2
+  resolution: "typescript@npm:5.7.2"
   bin:
     tsc: bin/tsc
     tsserver: bin/tsserver
-  checksum: 10c0/3ed8297a8c7c56b7fec282532503d1ac795239d06e7c4966b42d4330c6cf433a170b53bcf93a130a7f14ccc5235de5560df4f1045eb7f3550b46ebed16d3c5e5
+  checksum: 10c0/a873118b5201b2ef332127ef5c63fb9d9c155e6fdbe211cbd9d8e65877283797cca76546bad742eea36ed7efbe3424a30376818f79c7318512064e8625d61622
   languageName: node
   linkType: hard
 
 "typescript@patch:typescript@npm%3A^5#optional!builtin<compat/typescript>":
-  version: 5.6.2
-  resolution: "typescript@patch:typescript@npm%3A5.6.2#optional!builtin<compat/typescript>::version=5.6.2&hash=b45daf"
+  version: 5.7.2
+  resolution: "typescript@patch:typescript@npm%3A5.7.2#optional!builtin<compat/typescript>::version=5.7.2&hash=b45daf"
   bin:
     tsc: bin/tsc
     tsserver: bin/tsserver
-  checksum: 10c0/e6c1662e4852e22fe4bbdca471dca3e3edc74f6f1df043135c44a18a7902037023ccb0abdfb754595ca9028df8920f2f8492c00fc3cbb4309079aae8b7de71cd
+  checksum: 10c0/c891ccf04008bc1305ba34053db951f8a4584b4a1bf2f68fd972c4a354df3dc5e62c8bfed4f6ac2d12e5b3b1c49af312c83a651048f818cd5b4949d17baacd79
   languageName: node
   linkType: hard
 
@@ -7784,6 +7723,7 @@ __metadata:
     isomorphic-fetch: "npm:^3.0.0"
     jest: "npm:^29.7.0"
     jest-environment-jsdom: "npm:^29.7.0"
+    jotai: "npm:^2.10.3"
     next: "npm:14.1.0"
     next-intl: "npm:^3.19.1"
     node-mocks-http: "npm:^1.14.1"
@@ -7801,21 +7741,21 @@ __metadata:
   languageName: unknown
   linkType: soft
 
-"unique-filename@npm:^3.0.0":
-  version: 3.0.0
-  resolution: "unique-filename@npm:3.0.0"
+"unique-filename@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "unique-filename@npm:4.0.0"
   dependencies:
-    unique-slug: "npm:^4.0.0"
-  checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f
+    unique-slug: "npm:^5.0.0"
+  checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc
   languageName: node
   linkType: hard
 
-"unique-slug@npm:^4.0.0":
-  version: 4.0.0
-  resolution: "unique-slug@npm:4.0.0"
+"unique-slug@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "unique-slug@npm:5.0.0"
   dependencies:
     imurmurhash: "npm:^0.1.4"
-  checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635
+  checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293
   languageName: node
   linkType: hard
 
@@ -7826,17 +7766,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"update-browserslist-db@npm:^1.1.0":
-  version: 1.1.0
-  resolution: "update-browserslist-db@npm:1.1.0"
+"update-browserslist-db@npm:^1.1.1":
+  version: 1.1.1
+  resolution: "update-browserslist-db@npm:1.1.1"
   dependencies:
-    escalade: "npm:^3.1.2"
-    picocolors: "npm:^1.0.1"
+    escalade: "npm:^3.2.0"
+    picocolors: "npm:^1.1.0"
   peerDependencies:
     browserslist: ">= 4.21.0"
   bin:
     update-browserslist-db: cli.js
-  checksum: 10c0/a7452de47785842736fb71547651c5bbe5b4dc1e3722ccf48a704b7b34e4dcf633991eaa8e4a6a517ffb738b3252eede3773bef673ef9021baa26b056d63a5b9
+  checksum: 10c0/536a2979adda2b4be81b07e311bd2f3ad5e978690987956bc5f514130ad50cac87cd22c710b686d79731e00fbee8ef43efe5fcd72baa241045209195d43dcc80
   languageName: node
   linkType: hard
 
@@ -7859,15 +7799,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"use-intl@npm:^3.19.4":
-  version: 3.19.4
-  resolution: "use-intl@npm:3.19.4"
+"use-intl@npm:^3.26.1":
+  version: 3.26.1
+  resolution: "use-intl@npm:3.26.1"
   dependencies:
     "@formatjs/fast-memoize": "npm:^2.2.0"
     intl-messageformat: "npm:^10.5.14"
   peerDependencies:
-    react: ^16.8.0 || ^17.0.0 || ^18.0.0
-  checksum: 10c0/f109d4e3e157cd64fb7c0c2e2f7ed62c009a9461e2b3eb17abc812515a9888bc783319392e7fec27c8aca85aa12cba1989ba74ae3a7b3a12f4ab37529e008e65
+    react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
+  checksum: 10c0/a6dd5681f393642da5b90e804237220eb7100102b78683def51cb8ffae6c7d7a6924699a0964ea62ab3198ea8b05182fe58b1832a4a700d4f948667641e66a3e
   languageName: node
   linkType: hard
 
@@ -7971,36 +7911,37 @@ __metadata:
   languageName: node
   linkType: hard
 
-"which-boxed-primitive@npm:^1.0.2":
-  version: 1.0.2
-  resolution: "which-boxed-primitive@npm:1.0.2"
+"which-boxed-primitive@npm:^1.0.2, which-boxed-primitive@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "which-boxed-primitive@npm:1.1.0"
   dependencies:
-    is-bigint: "npm:^1.0.1"
-    is-boolean-object: "npm:^1.1.0"
-    is-number-object: "npm:^1.0.4"
-    is-string: "npm:^1.0.5"
-    is-symbol: "npm:^1.0.3"
-  checksum: 10c0/0a62a03c00c91dd4fb1035b2f0733c341d805753b027eebd3a304b9cb70e8ce33e25317add2fe9b5fea6f53a175c0633ae701ff812e604410ddd049777cd435e
+    is-bigint: "npm:^1.1.0"
+    is-boolean-object: "npm:^1.2.0"
+    is-number-object: "npm:^1.1.0"
+    is-string: "npm:^1.1.0"
+    is-symbol: "npm:^1.1.0"
+  checksum: 10c0/ee4e4bcf0026aeeda1b28d005ddfcf1d8d6025d1cf04b2271f8dbbdd13df9357ba7da657ec2d886520bccf8d93d9535454e44f38f201c5461a2fe7c838b455de
   languageName: node
   linkType: hard
 
-"which-builtin-type@npm:^1.1.3":
-  version: 1.1.4
-  resolution: "which-builtin-type@npm:1.1.4"
+"which-builtin-type@npm:^1.2.0":
+  version: 1.2.1
+  resolution: "which-builtin-type@npm:1.2.1"
   dependencies:
+    call-bound: "npm:^1.0.2"
     function.prototype.name: "npm:^1.1.6"
     has-tostringtag: "npm:^1.0.2"
     is-async-function: "npm:^2.0.0"
-    is-date-object: "npm:^1.0.5"
-    is-finalizationregistry: "npm:^1.0.2"
+    is-date-object: "npm:^1.1.0"
+    is-finalizationregistry: "npm:^1.1.0"
     is-generator-function: "npm:^1.0.10"
-    is-regex: "npm:^1.1.4"
+    is-regex: "npm:^1.2.1"
     is-weakref: "npm:^1.0.2"
     isarray: "npm:^2.0.5"
-    which-boxed-primitive: "npm:^1.0.2"
+    which-boxed-primitive: "npm:^1.1.0"
     which-collection: "npm:^1.0.2"
-    which-typed-array: "npm:^1.1.15"
-  checksum: 10c0/a4a76d20d869a81b1dbb4adea31edc7e6c1a4466d3ab7c2cd757c9219d48d3723b04076c85583257b0f0f8e3ebe5af337248b8ceed57b9051cb97bce5bd881d1
+    which-typed-array: "npm:^1.1.16"
+  checksum: 10c0/8dcf323c45e5c27887800df42fbe0431d0b66b1163849bb7d46b5a730ad6a96ee8bfe827d078303f825537844ebf20c02459de41239a0a9805e2fcb3cae0d471
   languageName: node
   linkType: hard
 
@@ -8016,16 +7957,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15":
-  version: 1.1.15
-  resolution: "which-typed-array@npm:1.1.15"
+"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.16":
+  version: 1.1.16
+  resolution: "which-typed-array@npm:1.1.16"
   dependencies:
     available-typed-arrays: "npm:^1.0.7"
     call-bind: "npm:^1.0.7"
     for-each: "npm:^0.3.3"
     gopd: "npm:^1.0.1"
     has-tostringtag: "npm:^1.0.2"
-  checksum: 10c0/4465d5348c044032032251be54d8988270e69c6b7154f8fcb2a47ff706fe36f7624b3a24246b8d9089435a8f4ec48c1c1025c5d6b499456b9e5eff4f48212983
+  checksum: 10c0/a9075293200db4fbce7c24d52731843542c5a19edfc66e31aa2cbefa788b5caa7ef05008f6e60d2c38d8198add6b92d0ddc2937918c5c308be398b1ebd8721af
   languageName: node
   linkType: hard
 
@@ -8040,14 +7981,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"which@npm:^4.0.0":
-  version: 4.0.0
-  resolution: "which@npm:4.0.0"
+"which@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "which@npm:5.0.0"
   dependencies:
     isexe: "npm:^3.1.1"
   bin:
     node-which: bin/which.js
-  checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a
+  checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b
   languageName: node
   linkType: hard
 
@@ -8147,12 +8088,19 @@ __metadata:
   languageName: node
   linkType: hard
 
+"yallist@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "yallist@npm:5.0.0"
+  checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416
+  languageName: node
+  linkType: hard
+
 "yaml@npm:^2.3.4":
-  version: 2.5.1
-  resolution: "yaml@npm:2.5.1"
+  version: 2.6.1
+  resolution: "yaml@npm:2.6.1"
   bin:
     yaml: bin.mjs
-  checksum: 10c0/40fba5682898dbeeb3319e358a968fe886509fab6f58725732a15f8dda3abac509f91e76817c708c9959a15f786f38ff863c1b88062d7c1162c5334a7d09cb4a
+  checksum: 10c0/aebf07f61c72b38c74d2b60c3a3ccf89ee4da45bcd94b2bfb7899ba07a5257625a7c9f717c65a6fc511563d48001e01deb1d9e55f0133f3e2edf86039c8c1be7
   languageName: node
   linkType: hard
 
@@ -8193,8 +8141,8 @@ __metadata:
   linkType: hard
 
 "zod@npm:^3.22.4":
-  version: 3.23.8
-  resolution: "zod@npm:3.23.8"
-  checksum: 10c0/8f14c87d6b1b53c944c25ce7a28616896319d95bc46a9660fe441adc0ed0a81253b02b5abdaeffedbeb23bdd25a0bf1c29d2c12dd919aef6447652dd295e3e69
+  version: 3.24.1
+  resolution: "zod@npm:3.24.1"
+  checksum: 10c0/0223d21dbaa15d8928fe0da3b54696391d8e3e1e2d0283a1a070b5980a1dbba945ce631c2d1eccc088fdbad0f2dfa40155590bf83732d3ac4fcca2cc9237591b
   languageName: node
   linkType: hard
-- 
GitLab


From e46ddbdeb019ddcb6bcfb1606721ef59de11560d Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Fri, 13 Dec 2024 15:47:25 +0100
Subject: [PATCH 04/55] refactored code in category bar to handle api call,
 reused component in details view

---
 src/app/[locale]/results/details/page.tsx     |   6 +-
 src/app/[locale]/results/page.tsx             | 102 +++-----------
 src/components/app/results/CategoryBar.tsx    | 131 +++++++++++++-----
 .../app/results/Details/RelatedResults.tsx    |  26 ++++
 src/components/layout/Error.tsx               |   2 +-
 src/components/layout/Spinner.tsx             |   2 +-
 6 files changed, 151 insertions(+), 118 deletions(-)
 create mode 100644 src/components/app/results/Details/RelatedResults.tsx

diff --git a/src/app/[locale]/results/details/page.tsx b/src/app/[locale]/results/details/page.tsx
index a2f90dd..38434d5 100644
--- a/src/app/[locale]/results/details/page.tsx
+++ b/src/app/[locale]/results/details/page.tsx
@@ -5,12 +5,13 @@ import React, { Suspense } from "react";
 
 import BackBar from "@/components/app/results/BackBar";
 import DetailsItemCard from "@/components/app/results/Details/DetailsItemCard";
+import RelatedResults from "@/components/app/results/Details/RelatedResults";
 
 //import { ResultItem } from "@/types/types";
 
 const DetailsComponent = () => {
   const searchParams = useSearchParams();
-  const activeCategory = searchParams.get("category");
+  const currentlyActiveCategory = searchParams.get("category");
   const searchText = searchParams.get("searchText") ?? undefined;
   const detailsText = searchParams.get("detailsText") ?? undefined;
 
@@ -18,7 +19,8 @@ const DetailsComponent = () => {
     <div className="flex flex-col md:px-10 lg:px-16 py-5 mb-8 bg-whitesmoke h-full">
       <BackBar />
       <DetailsItemCard />
-      <div>{activeCategory}</div>
+      <RelatedResults />
+      <div>{currentlyActiveCategory}</div>
       <div>{searchText}</div>
       <div>{detailsText}</div>
     </div>
diff --git a/src/app/[locale]/results/page.tsx b/src/app/[locale]/results/page.tsx
index c65a6fd..70edcad 100644
--- a/src/app/[locale]/results/page.tsx
+++ b/src/app/[locale]/results/page.tsx
@@ -1,102 +1,38 @@
 "use client";
 
-import { useSearchParams } from "next/navigation";
-import React, { Suspense, useEffect, useRef, useState } from "react";
+import React, { Suspense, useState } from "react";
 
 import BackBar from "@/components/app/results/BackBar";
 import CategoryBar from "@/components/app/results/CategoryBar";
 import ListResults from "@/components/app/results/ListResults";
 import Error from "@/components/layout/Error";
 import MobileSearch from "@/components/layout/MobileSearch";
-import Spinner from "@/components/layout/Spinner";
 import type { Category } from "@/types/types";
-import { getAllCategories, getCategoryCounts } from "@/utils/apiCall";
 
 const ResultsComponent = () => {
-  const resultParams = useSearchParams();
-
-  const [categories, setCategories] = useState<Category[]>([]);
-  const [baseCategories, setBaseCategories] = useState<Category[]>([]);
-  const [activeCategory, setCategory] = useState<Category>();
-  const [categoryLoading, setCategoryLoading] = useState(true);
+  //const resultParams = useSearchParams();
   const [hasBcError, setHasBcError] = useState(false);
   const [hasSearchError, setHasSearchError] = useState(false);
-
-  const firstRender = useRef(true);
-
-  const category = resultParams.get("category");
-  const searchText = resultParams.get("searchText") ?? undefined;
-
-  useEffect(() => {
-    const loadCategories = async () => {
-      setCategoryLoading(true);
-      try {
-        const categories = await getAllCategories();
-        setBaseCategories(categories);
-      } catch (error) {
-        setHasBcError(true);
-      } finally {
-        setCategoryLoading(false);
-      }
-    };
-
-    loadCategories().catch(console.error);
-  }, []);
-
-  useEffect(() => {
-    if (!activeCategory && categories.length) {
-      setCategory(categories[0]);
-    }
-  }, [activeCategory, categories]);
-
-  useEffect(() => {
-    categories.forEach((cat: Category) => (cat.id === category ? setCategory(cat) : null));
-  }, [category, categories]);
-
-  useEffect(() => {
-    const updateCategoryCount = async () => {
-      try {
-        setHasSearchError(false);
-        const categoryCounts = await getCategoryCounts(searchText);
-        const categories = structuredClone(baseCategories);
-
-        categories.forEach((cat: Category) => (cat.count = categoryCounts[cat.id] ?? 0));
-        setCategories(categories);
-      } catch (error) {
-        console.error("Failed to fetch category counts", error);
-        setHasSearchError(true);
-      } finally {
-        setCategoryLoading(false);
-      }
-    };
-
-    if (firstRender.current) {
-      firstRender.current = false;
-    } else {
-      updateCategoryCount().catch(console.error);
-    }
-  }, [baseCategories, searchText]);
+  const [activeCategory, setActiveCategory] = useState<Category>();
 
   return (
     <div className="grow flex flex-col justify-start">
-      {categoryLoading ? (
-        <Spinner />
-      ) : hasBcError || hasSearchError ? (
-        <Error />
-      ) : (
-        <>
-          <CategoryBar
-            categories={categories}
-            category={activeCategory}
-            setCategory={setCategory}
-          />
-          <div className="flex flex-col md:px-10 lg:px-16 py-5 mb-8 bg-whitesmoke h-full">
-            <BackBar />
-            <MobileSearch />
-            {activeCategory && <ListResults activeCategory={activeCategory} />}
-          </div>
-        </>
-      )}
+      <>
+        <CategoryBar
+          activeCategory={activeCategory}
+          hasBcError={hasBcError}
+          hasSearchError={hasSearchError}
+          setActiveCategory={setActiveCategory}
+          setHasBcError={setHasBcError}
+          setHasSearchError={setHasSearchError}
+        />
+        <div className="flex flex-col md:px-10 lg:px-16 py-5 mb-8 bg-whitesmoke h-full">
+          <BackBar />
+          <MobileSearch />
+          {activeCategory && <ListResults activeCategory={activeCategory} />}
+        </div>
+      </>
+      {hasBcError || hasSearchError ? <Error /> : null}
     </div>
   );
 };
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index b3dfd54..1b91cf5 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -1,49 +1,118 @@
+"use client";
 import { useSearchParams } from "next/navigation";
 import { useTranslations } from "next-intl";
-import { Dispatch, SetStateAction, Suspense } from "react";
+import { Dispatch, SetStateAction, Suspense, useEffect, useState, useRef } from "react";
 
 import { Link } from "@/i18n";
 import type { Category } from "@/types/types";
+import { getAllCategories, getCategoryCounts } from "@/utils/apiCall";
 
 type Props = {
-  categories: Category[];
-  category?: Category;
-  setCategory: Dispatch<SetStateAction<Category | undefined>>;
+  activeCategory?: Category;
+  hasBcError: boolean;
+  hasSearchError: boolean;
+  setActiveCategory: Dispatch<SetStateAction<Category | undefined>>;
+  setHasBcError: Dispatch<SetStateAction<boolean>>;
+  setHasSearchError: Dispatch<SetStateAction<boolean>>;
 };
 
-const CategoryBarComponent = ({ categories, category, setCategory }: Props) => {
+const CategoryBarComponent = ({
+  activeCategory,
+  hasBcError,
+  hasSearchError,
+  setActiveCategory,
+  setHasBcError,
+  setHasSearchError,
+}: Props) => {
   const c = useTranslations("Categories");
   const resultParams = useSearchParams();
-  const searchText = resultParams.get("searchText");
+  //const searchText = resultParams.get("searchText");
   const formatter = Intl.NumberFormat("en", { notation: "compact" });
+
+  const [categories, setCategories] = useState<Category[]>([]);
+  const [baseCategories, setBaseCategories] = useState<Category[]>([]);
+
+  const firstRender = useRef(true);
+
+  const category = resultParams.get("category");
+  const searchText = resultParams.get("searchText") ?? undefined;
   const search = searchText ? `&searchText=${searchText}` : "";
 
+  useEffect(() => {
+    const loadCategories = async () => {
+      try {
+        const categories = await getAllCategories();
+        setBaseCategories(categories);
+      } catch (error) {
+        setHasBcError(true);
+      }
+    };
+
+    loadCategories().catch(console.error);
+  }, [setHasBcError]);
+
+  useEffect(() => {
+    if (!activeCategory && categories.length) {
+      setActiveCategory(categories[0]);
+    }
+  }, [activeCategory, categories, setActiveCategory]);
+
+  useEffect(() => {
+    categories.forEach((cat: Category) => (cat.id === category ? setActiveCategory(cat) : null));
+  }, [category, categories, setActiveCategory]);
+
+  useEffect(() => {
+    const updateCategoryCount = async () => {
+      try {
+        setHasSearchError(false);
+        const categoryCounts = await getCategoryCounts(searchText);
+        const categories = structuredClone(baseCategories);
+
+        categories.forEach((cat: Category) => (cat.count = categoryCounts[cat.id] ?? 0));
+        setCategories(categories);
+      } catch (error) {
+        console.error("Failed to fetch category counts", error);
+        setHasSearchError(true);
+      }
+    };
+
+    if (firstRender.current) {
+      firstRender.current = false;
+    } else {
+      updateCategoryCount().catch(console.error);
+    }
+  }, [baseCategories, searchText, setHasSearchError, setHasBcError]);
+
   return (
-    <div className="bg-primary-helmholtz-dunkelblau text-primary-helmholtz-weiss grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 2xl:flex gap-y-2 gap-x-2 xl:gap-x-6 px-4 pt-2 pb-3 md:px-10 lg:px-16 xl:pt-4 xl:min-h-24">
-      {categories.map((o, idx) => (
-        <Link
-          href={`/results?category=${o.id}${search}`}
-          shallow
-          onClick={() => setCategory(o)}
-          key={idx}
-          className={`${
-            o.id === category?.id
-              ? "font-semibold underline decoration-secondary-helmholtz-mint underline-offset-[20px]"
-              : "text-blue-100 hover:rounded-full hover:bg-white/[0.12] hover:font-medium hover:py-3 hover:px-2"
-          } flex place-content-center cursor-pointer text-md w-full flex-1 py-2 font-normal text-primary-helmholtz-weiss `}
-        >
-          <div className="xl:basis-1/4 2xl:basis-1/5 mr-2 ">
-            {/* count indicator for category */}
-            <span className="inline-flex h-11 w-11 place-content-center rounded-full bg-primary-helmholtz-hellblau object-contain align-middle">
-              <span className="self-center font-medium text-primary-helmholtz-weiss">
-                {formatter.format(o.count)}
-              </span>
-            </span>
-          </div>
-          <div className="basis-2/3 self-center text-left">{c(o.id, { count: o.count })}</div>
-        </Link>
-      ))}
-    </div>
+    <>
+      {hasBcError || hasSearchError ? null : (
+        <div className="bg-primary-helmholtz-dunkelblau text-primary-helmholtz-weiss grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 2xl:flex gap-y-2 gap-x-2 xl:gap-x-6 px-4 pt-2 pb-3 md:px-10 lg:px-16 xl:pt-4 xl:min-h-24">
+          {categories.map((o, idx) => (
+            <Link
+              href={`/results?category=${o.id}${search}`}
+              shallow
+              onClick={() => setActiveCategory(o)}
+              key={idx}
+              className={`${
+                o.id === activeCategory?.id
+                  ? "font-semibold underline decoration-secondary-helmholtz-mint underline-offset-[20px]"
+                  : "text-blue-100 hover:rounded-full hover:bg-white/[0.12] hover:font-medium hover:py-3 hover:px-2"
+              } flex place-content-center cursor-pointer text-md w-full flex-1 py-2 font-normal text-primary-helmholtz-weiss `}
+            >
+              <div className="xl:basis-1/4 2xl:basis-1/5 mr-2 ">
+                {/* count indicator for category */}
+                <span className="inline-flex h-11 w-11 place-content-center rounded-full bg-primary-helmholtz-hellblau object-contain align-middle">
+                  <span className="self-center font-medium text-primary-helmholtz-weiss">
+                    {formatter.format(o.count)}
+                  </span>
+                </span>
+              </div>
+              <div className="basis-2/3 self-center text-left">{c(o.id, { count: o.count })}</div>
+            </Link>
+          ))}
+        </div>
+      )}
+    </>
   );
 };
 
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
new file mode 100644
index 0000000..4fa0e54
--- /dev/null
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -0,0 +1,26 @@
+import React, { useState } from "react";
+
+import Error from "@/components/layout/Error";
+import { Category } from "@/types/types";
+
+import CategoryBar from "../CategoryBar";
+const RelatedResults = () => {
+  const [hasBcError, setHasBcError] = useState(false);
+  const [hasSearchError, setHasSearchError] = useState(false);
+  const [activeCategory, setActiveCategory] = useState<Category>();
+  return (
+    <div className="m-4 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-4 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white">
+      <CategoryBar
+        activeCategory={activeCategory}
+        hasBcError={hasBcError}
+        hasSearchError={hasSearchError}
+        setActiveCategory={setActiveCategory}
+        setHasBcError={setHasBcError}
+        setHasSearchError={setHasSearchError}
+      />
+      {hasBcError || hasSearchError ? <Error /> : null}
+    </div>
+  );
+};
+
+export default RelatedResults;
diff --git a/src/components/layout/Error.tsx b/src/components/layout/Error.tsx
index 472b2d6..0b940c1 100644
--- a/src/components/layout/Error.tsx
+++ b/src/components/layout/Error.tsx
@@ -4,7 +4,7 @@ import React from "react";
 import ErrorWarning from "@/resources/images/misc/error-warning.png";
 const Error = () => {
   return (
-    <div className="grow flex flex-col justify-center items-center p-10 ">
+    <div className="grow flex flex-col justify-center items-center p-10 bg-whitesmoke h-full">
       {/* TODO: change the font on the icon */}
       <Image
         src={ErrorWarning || ""}
diff --git a/src/components/layout/Spinner.tsx b/src/components/layout/Spinner.tsx
index a2ee151..e06cbfe 100644
--- a/src/components/layout/Spinner.tsx
+++ b/src/components/layout/Spinner.tsx
@@ -1,5 +1,5 @@
 const Spinner = () => (
-  <div className="grow flex flex-col p-10">
+  <div className="grow flex flex-col p-10 bg-whitesmoke h-full">
     <svg
       className="m-auto align-middle max-h-20 max-w-20 animate-spin text-secondary-helmholtz-mint"
       xmlns="http://www.w3.org/2000/svg"
-- 
GitLab


From 035bb867eb152d3904381d20a94c9f6650fdb40d Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Fri, 13 Dec 2024 17:09:01 +0100
Subject: [PATCH 05/55] updated workflow of category bar to show only
 unselected categories in details view and all categories in normal results
 view

---
 src/components/app/results/CategoryBar.tsx    | 31 ++++++++++++++-----
 .../app/results/Details/RelatedResults.tsx    |  8 ++++-
 2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index 1b91cf5..7614a8e 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -14,12 +14,14 @@ type Props = {
   setActiveCategory: Dispatch<SetStateAction<Category | undefined>>;
   setHasBcError: Dispatch<SetStateAction<boolean>>;
   setHasSearchError: Dispatch<SetStateAction<boolean>>;
+  inDetailsView?: boolean;
 };
 
 const CategoryBarComponent = ({
   activeCategory,
   hasBcError,
   hasSearchError,
+  inDetailsView,
   setActiveCategory,
   setHasBcError,
   setHasSearchError,
@@ -28,28 +30,35 @@ const CategoryBarComponent = ({
   const resultParams = useSearchParams();
   //const searchText = resultParams.get("searchText");
   const formatter = Intl.NumberFormat("en", { notation: "compact" });
-
+  //const [category, setCategory] = useState<Category>();
   const [categories, setCategories] = useState<Category[]>([]);
   const [baseCategories, setBaseCategories] = useState<Category[]>([]);
 
   const firstRender = useRef(true);
 
-  const category = resultParams.get("category");
+  const currentlyActivecategory = resultParams.get("category") ?? undefined;
   const searchText = resultParams.get("searchText") ?? undefined;
+  const detailsText = resultParams.get("detailsText") ?? undefined;
+
+  const details = detailsText ? `&detailsText=${detailsText}` : "";
   const search = searchText ? `&searchText=${searchText}` : "";
 
   useEffect(() => {
     const loadCategories = async () => {
       try {
-        const categories = await getAllCategories();
-        setBaseCategories(categories);
+        const allCategories = await getAllCategories();
+        if (inDetailsView && currentlyActivecategory) {
+          setBaseCategories(allCategories.filter((cat) => cat.id !== currentlyActivecategory));
+        } else {
+          setBaseCategories(allCategories);
+        }
       } catch (error) {
         setHasBcError(true);
       }
     };
 
     loadCategories().catch(console.error);
-  }, [setHasBcError]);
+  }, [inDetailsView, currentlyActivecategory, setHasBcError]);
 
   useEffect(() => {
     if (!activeCategory && categories.length) {
@@ -58,8 +67,10 @@ const CategoryBarComponent = ({
   }, [activeCategory, categories, setActiveCategory]);
 
   useEffect(() => {
-    categories.forEach((cat: Category) => (cat.id === category ? setActiveCategory(cat) : null));
-  }, [category, categories, setActiveCategory]);
+    categories.forEach((cat: Category) =>
+      cat.id === currentlyActivecategory ? setActiveCategory(cat) : null
+    );
+  }, [currentlyActivecategory, categories, setActiveCategory]);
 
   useEffect(() => {
     const updateCategoryCount = async () => {
@@ -89,7 +100,11 @@ const CategoryBarComponent = ({
         <div className="bg-primary-helmholtz-dunkelblau text-primary-helmholtz-weiss grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 2xl:flex gap-y-2 gap-x-2 xl:gap-x-6 px-4 pt-2 pb-3 md:px-10 lg:px-16 xl:pt-4 xl:min-h-24">
           {categories.map((o, idx) => (
             <Link
-              href={`/results?category=${o.id}${search}`}
+              href={
+                inDetailsView
+                  ? `/results/details?&category=${currentlyActivecategory}${search}${details}`
+                  : `/results?category=${o.id}${search}`
+              }
               shallow
               onClick={() => setActiveCategory(o)}
               key={idx}
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index 4fa0e54..b68c5cd 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
 
 import Error from "@/components/layout/Error";
 import { Category } from "@/types/types";
@@ -8,6 +8,11 @@ const RelatedResults = () => {
   const [hasBcError, setHasBcError] = useState(false);
   const [hasSearchError, setHasSearchError] = useState(false);
   const [activeCategory, setActiveCategory] = useState<Category>();
+
+  useEffect(() => {
+    console.log("new active category in details view", activeCategory);
+  }, [activeCategory]);
+
   return (
     <div className="m-4 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-4 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white">
       <CategoryBar
@@ -17,6 +22,7 @@ const RelatedResults = () => {
         setActiveCategory={setActiveCategory}
         setHasBcError={setHasBcError}
         setHasSearchError={setHasSearchError}
+        inDetailsView
       />
       {hasBcError || hasSearchError ? <Error /> : null}
     </div>
-- 
GitLab


From 2a088c6ee4dcb9616cd5fb82ebf8e6698a28c836 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Fri, 13 Dec 2024 17:12:49 +0100
Subject: [PATCH 06/55] code clean up

---
 src/app/[locale]/results/page.tsx               |  1 -
 src/components/app/results/CategoryBar.tsx      | 17 ++++++++---------
 .../app/results/Details/RelatedResults.tsx      |  4 ----
 3 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/src/app/[locale]/results/page.tsx b/src/app/[locale]/results/page.tsx
index 70edcad..32b3524 100644
--- a/src/app/[locale]/results/page.tsx
+++ b/src/app/[locale]/results/page.tsx
@@ -10,7 +10,6 @@ import MobileSearch from "@/components/layout/MobileSearch";
 import type { Category } from "@/types/types";
 
 const ResultsComponent = () => {
-  //const resultParams = useSearchParams();
   const [hasBcError, setHasBcError] = useState(false);
   const [hasSearchError, setHasSearchError] = useState(false);
   const [activeCategory, setActiveCategory] = useState<Category>();
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index 7614a8e..ea072d5 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -27,22 +27,21 @@ const CategoryBarComponent = ({
   setHasSearchError,
 }: Props) => {
   const c = useTranslations("Categories");
-  const resultParams = useSearchParams();
-  //const searchText = resultParams.get("searchText");
-  const formatter = Intl.NumberFormat("en", { notation: "compact" });
-  //const [category, setCategory] = useState<Category>();
-  const [categories, setCategories] = useState<Category[]>([]);
-  const [baseCategories, setBaseCategories] = useState<Category[]>([]);
-
-  const firstRender = useRef(true);
 
+  const resultParams = useSearchParams();
   const currentlyActivecategory = resultParams.get("category") ?? undefined;
   const searchText = resultParams.get("searchText") ?? undefined;
   const detailsText = resultParams.get("detailsText") ?? undefined;
-
   const details = detailsText ? `&detailsText=${detailsText}` : "";
   const search = searchText ? `&searchText=${searchText}` : "";
 
+  const formatter = Intl.NumberFormat("en", { notation: "compact" });
+
+  const [categories, setCategories] = useState<Category[]>([]);
+  const [baseCategories, setBaseCategories] = useState<Category[]>([]);
+
+  const firstRender = useRef(true);
+
   useEffect(() => {
     const loadCategories = async () => {
       try {
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index b68c5cd..678a317 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -9,10 +9,6 @@ const RelatedResults = () => {
   const [hasSearchError, setHasSearchError] = useState(false);
   const [activeCategory, setActiveCategory] = useState<Category>();
 
-  useEffect(() => {
-    console.log("new active category in details view", activeCategory);
-  }, [activeCategory]);
-
   return (
     <div className="m-4 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-4 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white">
       <CategoryBar
-- 
GitLab


From dbf5bfce3ae70983df5bdba7ce371e2fe7d29a65 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Fri, 13 Dec 2024 17:14:19 +0100
Subject: [PATCH 07/55] some more code clean up and formatting

---
 src/app/[locale]/results/details/page.tsx             | 2 --
 src/components/app/results/CategoryBar.tsx            | 2 +-
 src/components/app/results/Details/RelatedResults.tsx | 2 +-
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/app/[locale]/results/details/page.tsx b/src/app/[locale]/results/details/page.tsx
index 38434d5..e640d6f 100644
--- a/src/app/[locale]/results/details/page.tsx
+++ b/src/app/[locale]/results/details/page.tsx
@@ -7,8 +7,6 @@ import BackBar from "@/components/app/results/BackBar";
 import DetailsItemCard from "@/components/app/results/Details/DetailsItemCard";
 import RelatedResults from "@/components/app/results/Details/RelatedResults";
 
-//import { ResultItem } from "@/types/types";
-
 const DetailsComponent = () => {
   const searchParams = useSearchParams();
   const currentlyActiveCategory = searchParams.get("category");
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index ea072d5..2874684 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -11,10 +11,10 @@ type Props = {
   activeCategory?: Category;
   hasBcError: boolean;
   hasSearchError: boolean;
+  inDetailsView?: boolean;
   setActiveCategory: Dispatch<SetStateAction<Category | undefined>>;
   setHasBcError: Dispatch<SetStateAction<boolean>>;
   setHasSearchError: Dispatch<SetStateAction<boolean>>;
-  inDetailsView?: boolean;
 };
 
 const CategoryBarComponent = ({
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index 678a317..a6aaead 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React, { useState } from "react";
 
 import Error from "@/components/layout/Error";
 import { Category } from "@/types/types";
-- 
GitLab


From 3f513dd57967cded3d0f367a61f8897b3cc479b6 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 6 Jan 2025 12:10:51 +0100
Subject: [PATCH 08/55] run an alternate search for related items and display
 them under the new category bar

---
 src/components/app/results/CategoryBar.tsx            |  9 +++++++--
 src/components/app/results/Details/RelatedResults.tsx |  3 +++
 src/components/app/results/ListResults.tsx            | 10 ++++++++--
 src/components/app/results/ListResults/ResultItem.tsx |  2 +-
 4 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index 2874684..98f169c 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -74,8 +74,13 @@ const CategoryBarComponent = ({
   useEffect(() => {
     const updateCategoryCount = async () => {
       try {
+        const updatedSearchText =
+          searchText || detailsText
+            ? (searchText ? searchText : "") + " " + (detailsText ? detailsText : "")
+            : undefined;
+
         setHasSearchError(false);
-        const categoryCounts = await getCategoryCounts(searchText);
+        const categoryCounts = await getCategoryCounts(updatedSearchText);
         const categories = structuredClone(baseCategories);
 
         categories.forEach((cat: Category) => (cat.count = categoryCounts[cat.id] ?? 0));
@@ -91,7 +96,7 @@ const CategoryBarComponent = ({
     } else {
       updateCategoryCount().catch(console.error);
     }
-  }, [baseCategories, searchText, setHasSearchError, setHasBcError]);
+  }, [baseCategories, searchText, detailsText, setHasSearchError, setHasBcError]);
 
   return (
     <>
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index a6aaead..bacba36 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -1,9 +1,11 @@
 import React, { useState } from "react";
 
+import ListResults from "@/components/app/results/ListResults";
 import Error from "@/components/layout/Error";
 import { Category } from "@/types/types";
 
 import CategoryBar from "../CategoryBar";
+
 const RelatedResults = () => {
   const [hasBcError, setHasBcError] = useState(false);
   const [hasSearchError, setHasSearchError] = useState(false);
@@ -20,6 +22,7 @@ const RelatedResults = () => {
         setHasSearchError={setHasSearchError}
         inDetailsView
       />
+      {activeCategory && <ListResults activeCategory={activeCategory} />}
       {hasBcError || hasSearchError ? <Error /> : null}
     </div>
   );
diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index 5a5f38e..f702a33 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -28,6 +28,7 @@ const ListResultsComponent = ({ activeCategory }: Props) => {
   const [availableFilters, setAvailableFilters] = useState<FilterEntity[]>([]);
   const [selectedFilters, setSelectedFilters] = useState<FilterEntity[]>([]);
   const searchText = resultParams.get("searchText") ?? undefined;
+  const detailsText = resultParams.get("detailsText") ?? undefined;
   // define this here to make it possible to change later
   const resultsPerPage = 10;
 
@@ -59,10 +60,15 @@ const ListResultsComponent = ({ activeCategory }: Props) => {
   useEffect(() => {
     const updateResultList = async () => {
       setDataLoading(true);
+      const updatedSearchText =
+        searchText || detailsText
+          ? (searchText ? searchText : "") + " " + (detailsText ? detailsText : "")
+          : undefined;
+
       try {
         const searchResult = await search(
           activeCategory?.id,
-          searchText,
+          updatedSearchText,
           resultsPerPage,
           start,
           selectedFilters
@@ -87,7 +93,7 @@ const ListResultsComponent = ({ activeCategory }: Props) => {
     };
 
     updateResultList().catch(console.error);
-  }, [activeCategory, searchText, start, resultsPerPage, selectedFilters]);
+  }, [activeCategory, searchText, detailsText, start, resultsPerPage, selectedFilters]);
 
   return (
     <>
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 6316785..8b523f9 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -108,7 +108,7 @@ const ResultItem = ({ item, idx, searchText, activeCategory, inDetailsPage }: Pr
   const handleDetailSearch = () => {
     setDetailsItem(() => item);
     router.push(
-      `/results/details?category=${activeCategory?.id}${searchText ? `&searchText=${searchText}` : ``}&detailsText=${item.id}`
+      `/results/details?category=${activeCategory?.id}${searchText ? `&searchText=${searchText}` : ``}&detailsText=${item.name}`
     );
   };
 
-- 
GitLab


From 4f801c4e48ce73f17133bef46d3cdb1aea378492 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 6 Jan 2025 12:24:34 +0100
Subject: [PATCH 09/55] code clean up and implemented resetting of page number
 on change of category by user

---
 src/app/[locale]/results/details/page.tsx             | 11 -----------
 src/components/app/results/BackBar.tsx                |  1 +
 src/components/app/results/CategoryBar.tsx            |  1 +
 src/components/app/results/Details/RelatedResults.tsx |  1 +
 src/components/app/results/ListResults.tsx            |  6 ++++++
 5 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/app/[locale]/results/details/page.tsx b/src/app/[locale]/results/details/page.tsx
index e640d6f..7411f9e 100644
--- a/src/app/[locale]/results/details/page.tsx
+++ b/src/app/[locale]/results/details/page.tsx
@@ -1,6 +1,3 @@
-"use client";
-
-import { useSearchParams } from "next/navigation";
 import React, { Suspense } from "react";
 
 import BackBar from "@/components/app/results/BackBar";
@@ -8,19 +5,11 @@ import DetailsItemCard from "@/components/app/results/Details/DetailsItemCard";
 import RelatedResults from "@/components/app/results/Details/RelatedResults";
 
 const DetailsComponent = () => {
-  const searchParams = useSearchParams();
-  const currentlyActiveCategory = searchParams.get("category");
-  const searchText = searchParams.get("searchText") ?? undefined;
-  const detailsText = searchParams.get("detailsText") ?? undefined;
-
   return (
     <div className="flex flex-col md:px-10 lg:px-16 py-5 mb-8 bg-whitesmoke h-full">
       <BackBar />
       <DetailsItemCard />
       <RelatedResults />
-      <div>{currentlyActiveCategory}</div>
-      <div>{searchText}</div>
-      <div>{detailsText}</div>
     </div>
   );
 };
diff --git a/src/components/app/results/BackBar.tsx b/src/components/app/results/BackBar.tsx
index 75c78c8..f88b68b 100644
--- a/src/components/app/results/BackBar.tsx
+++ b/src/components/app/results/BackBar.tsx
@@ -1,3 +1,4 @@
+"use client";
 import { useRouter } from "next/navigation";
 import React from "react";
 
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index 98f169c..b82b669 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -1,4 +1,5 @@
 "use client";
+
 import { useSearchParams } from "next/navigation";
 import { useTranslations } from "next-intl";
 import { Dispatch, SetStateAction, Suspense, useEffect, useState, useRef } from "react";
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index bacba36..4d617c7 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -1,3 +1,4 @@
+"use client";
 import React, { useState } from "react";
 
 import ListResults from "@/components/app/results/ListResults";
diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index f702a33..3ad13a8 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -1,3 +1,5 @@
+"use client";
+
 import { useSearchParams } from "next/navigation";
 import { useTranslations } from "next-intl";
 import React, { Suspense, useEffect, useState } from "react";
@@ -57,6 +59,10 @@ const ListResultsComponent = ({ activeCategory }: Props) => {
     return withEnrichedRecords;
   };
 
+  useEffect(() => {
+    setPage(0);
+  }, [activeCategory]);
+
   useEffect(() => {
     const updateResultList = async () => {
       setDataLoading(true);
-- 
GitLab


From 5ec271497ef443de5fd063853353a3c6595c9bf0 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 7 Jan 2025 11:23:07 +0100
Subject: [PATCH 10/55] handle loading of information in the views

---
 src/app/[locale]/results/page.tsx             | 23 ++++++--
 src/components/app/results/CategoryBar.tsx    | 19 ++++++-
 .../app/results/Details/RelatedResults.tsx    | 33 +++++++----
 src/components/app/results/ListResults.tsx    | 56 ++++++++++---------
 4 files changed, 86 insertions(+), 45 deletions(-)

diff --git a/src/app/[locale]/results/page.tsx b/src/app/[locale]/results/page.tsx
index 32b3524..5a0f928 100644
--- a/src/app/[locale]/results/page.tsx
+++ b/src/app/[locale]/results/page.tsx
@@ -7,11 +7,14 @@ import CategoryBar from "@/components/app/results/CategoryBar";
 import ListResults from "@/components/app/results/ListResults";
 import Error from "@/components/layout/Error";
 import MobileSearch from "@/components/layout/MobileSearch";
+import Spinner from "@/components/layout/Spinner";
 import type { Category } from "@/types/types";
 
 const ResultsComponent = () => {
   const [hasBcError, setHasBcError] = useState(false);
   const [hasSearchError, setHasSearchError] = useState(false);
+  const [categoryLoading, setCategoryLoading] = useState(true);
+  const [resultsLoading, setResultsLoading] = useState(true);
   const [activeCategory, setActiveCategory] = useState<Category>();
 
   return (
@@ -19,19 +22,31 @@ const ResultsComponent = () => {
       <>
         <CategoryBar
           activeCategory={activeCategory}
+          categoryLoading={categoryLoading}
+          setCategoryLoading={setCategoryLoading}
           hasBcError={hasBcError}
           hasSearchError={hasSearchError}
           setActiveCategory={setActiveCategory}
           setHasBcError={setHasBcError}
           setHasSearchError={setHasSearchError}
+          inDetailsView={false}
         />
         <div className="flex flex-col md:px-10 lg:px-16 py-5 mb-8 bg-whitesmoke h-full">
-          <BackBar />
-          <MobileSearch />
-          {activeCategory && <ListResults activeCategory={activeCategory} />}
+          {!categoryLoading && !resultsLoading ? (
+            <>
+              <BackBar />
+              <MobileSearch />
+            </>
+          ) : null}
+
+          {activeCategory && (
+            <ListResults activeCategory={activeCategory} setResultsLoading={setResultsLoading} />
+          )}
         </div>
       </>
-      {hasBcError || hasSearchError ? <Error /> : null}
+
+      {(categoryLoading || resultsLoading) && <Spinner />}
+      {(hasBcError || hasSearchError) && <Error />}
     </div>
   );
 };
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index b82b669..d2bb399 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -10,20 +10,24 @@ import { getAllCategories, getCategoryCounts } from "@/utils/apiCall";
 
 type Props = {
   activeCategory?: Category;
+  categoryLoading: boolean;
   hasBcError: boolean;
   hasSearchError: boolean;
   inDetailsView?: boolean;
   setActiveCategory: Dispatch<SetStateAction<Category | undefined>>;
   setHasBcError: Dispatch<SetStateAction<boolean>>;
   setHasSearchError: Dispatch<SetStateAction<boolean>>;
+  setCategoryLoading: Dispatch<SetStateAction<boolean>>;
 };
 
 const CategoryBarComponent = ({
   activeCategory,
+  categoryLoading,
   hasBcError,
   hasSearchError,
   inDetailsView,
   setActiveCategory,
+  setCategoryLoading,
   setHasBcError,
   setHasSearchError,
 }: Props) => {
@@ -75,12 +79,12 @@ const CategoryBarComponent = ({
   useEffect(() => {
     const updateCategoryCount = async () => {
       try {
+        setHasSearchError(false);
         const updatedSearchText =
           searchText || detailsText
             ? (searchText ? searchText : "") + " " + (detailsText ? detailsText : "")
             : undefined;
 
-        setHasSearchError(false);
         const categoryCounts = await getCategoryCounts(updatedSearchText);
         const categories = structuredClone(baseCategories);
 
@@ -89,6 +93,8 @@ const CategoryBarComponent = ({
       } catch (error) {
         console.error("Failed to fetch category counts", error);
         setHasSearchError(true);
+      } finally {
+        setCategoryLoading(false);
       }
     };
 
@@ -97,11 +103,18 @@ const CategoryBarComponent = ({
     } else {
       updateCategoryCount().catch(console.error);
     }
-  }, [baseCategories, searchText, detailsText, setHasSearchError, setHasBcError]);
+  }, [
+    baseCategories,
+    searchText,
+    detailsText,
+    setCategoryLoading,
+    setHasSearchError,
+    setHasBcError,
+  ]);
 
   return (
     <>
-      {hasBcError || hasSearchError ? null : (
+      {categoryLoading || hasBcError || hasSearchError ? null : (
         <div className="bg-primary-helmholtz-dunkelblau text-primary-helmholtz-weiss grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 2xl:flex gap-y-2 gap-x-2 xl:gap-x-6 px-4 pt-2 pb-3 md:px-10 lg:px-16 xl:pt-4 xl:min-h-24">
           {categories.map((o, idx) => (
             <Link
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index 4d617c7..1c5228a 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -3,28 +3,39 @@ import React, { useState } from "react";
 
 import ListResults from "@/components/app/results/ListResults";
 import Error from "@/components/layout/Error";
+import Spinner from "@/components/layout/Spinner";
 import { Category } from "@/types/types";
 
 import CategoryBar from "../CategoryBar";
 
 const RelatedResults = () => {
+  const [categoryLoading, setCategoryLoading] = useState(true);
+  const [resultsLoading, setResultsLoading] = useState(true);
   const [hasBcError, setHasBcError] = useState(false);
   const [hasSearchError, setHasSearchError] = useState(false);
   const [activeCategory, setActiveCategory] = useState<Category>();
 
   return (
     <div className="m-4 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-4 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white">
-      <CategoryBar
-        activeCategory={activeCategory}
-        hasBcError={hasBcError}
-        hasSearchError={hasSearchError}
-        setActiveCategory={setActiveCategory}
-        setHasBcError={setHasBcError}
-        setHasSearchError={setHasSearchError}
-        inDetailsView
-      />
-      {activeCategory && <ListResults activeCategory={activeCategory} />}
-      {hasBcError || hasSearchError ? <Error /> : null}
+      <>
+        <CategoryBar
+          activeCategory={activeCategory}
+          categoryLoading={categoryLoading}
+          setCategoryLoading={setCategoryLoading}
+          hasBcError={hasBcError}
+          hasSearchError={hasSearchError}
+          setActiveCategory={setActiveCategory}
+          setHasBcError={setHasBcError}
+          setHasSearchError={setHasSearchError}
+          inDetailsView
+        />
+        {activeCategory && (
+          <ListResults activeCategory={activeCategory} setResultsLoading={setResultsLoading} />
+        )}
+      </>
+
+      {(categoryLoading || resultsLoading) ?? <Spinner />}
+      {(hasBcError || hasSearchError) ?? <Error />}
     </div>
   );
 };
diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index 3ad13a8..dfa0581 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -2,7 +2,7 @@
 
 import { useSearchParams } from "next/navigation";
 import { useTranslations } from "next-intl";
-import React, { Suspense, useEffect, useState } from "react";
+import React, { Suspense, useEffect, useState, Dispatch, SetStateAction } from "react";
 
 import Filters from "@/components/app/results/ListResults/Filters";
 import NoResults from "@/components/app/results/ListResults/NoResults";
@@ -10,19 +10,18 @@ import Pagination from "@/components/app/results/ListResults/Pagination";
 import ResultItem from "@/components/app/results/ListResults/ResultItem";
 import SelectedFiltersBar from "@/components/app/results/ListResults/SelectedFiltersBar";
 import Error from "@/components/layout/Error";
-import Spinner from "@/components/layout/Spinner";
 import type { Category, FilterEntity, ResultItem as ResultItemType } from "@/types/types";
 import { search, getRorInfo } from "@/utils/apiCall";
 
 type Props = {
   activeCategory: Category;
+  setResultsLoading: Dispatch<SetStateAction<boolean>>;
 };
 
-const ListResultsComponent = ({ activeCategory }: Props) => {
+const ListResultsComponent = ({ activeCategory, setResultsLoading }: Props) => {
   const t = useTranslations("ListResults");
   const s = useTranslations("Categories");
   const resultParams = useSearchParams();
-  const [dataLoading, setDataLoading] = useState(true);
   const [hasError, setHasError] = useState(false);
   const [start, setStart] = useState(0);
   const [results, setResults] = useState<ResultItemType[]>([]);
@@ -65,7 +64,6 @@ const ListResultsComponent = ({ activeCategory }: Props) => {
 
   useEffect(() => {
     const updateResultList = async () => {
-      setDataLoading(true);
       const updatedSearchText =
         searchText || detailsText
           ? (searchText ? searchText : "") + " " + (detailsText ? detailsText : "")
@@ -87,19 +85,26 @@ const ListResultsComponent = ({ activeCategory }: Props) => {
         } else {
           setResults(searchResult.records);
         }
-
         setSearchCount(searchResult.totalCount);
         setAvailableFilters(searchResult.filters);
       } catch (error) {
         console.log("Error on updating result list", error);
         setHasError(true);
       } finally {
-        setDataLoading(false);
+        setResultsLoading(false);
       }
     };
 
     updateResultList().catch(console.error);
-  }, [activeCategory, searchText, detailsText, start, resultsPerPage, selectedFilters]);
+  }, [
+    activeCategory,
+    searchText,
+    detailsText,
+    start,
+    resultsPerPage,
+    selectedFilters,
+    setResultsLoading,
+  ]);
 
   return (
     <>
@@ -147,25 +152,22 @@ const ListResultsComponent = ({ activeCategory }: Props) => {
               pageCount={searchCount / resultsPerPage}
               onPageChange={setPage}
             />
-            {dataLoading ? (
-              <Spinner />
-            ) : (
-              <div className="flex flex-col py-5 xl:py-8">
-                {results.length ? (
-                  results.map((item: ResultItemType) => (
-                    <ResultItem
-                      key={item.id}
-                      item={item}
-                      idx={item.id}
-                      activeCategory={activeCategory}
-                      searchText={searchText}
-                    />
-                  ))
-                ) : (
-                  <NoResults />
-                )}
-              </div>
-            )}
+
+            <div className="flex flex-col py-5 xl:py-8">
+              {results.length ? (
+                results.map((item: ResultItemType) => (
+                  <ResultItem
+                    key={item.id}
+                    item={item}
+                    idx={item.id}
+                    activeCategory={activeCategory}
+                    searchText={searchText}
+                  />
+                ))
+              ) : (
+                <NoResults />
+              )}
+            </div>
             <Pagination
               currentPage={start / 10}
               pageCount={searchCount / resultsPerPage}
-- 
GitLab


From 5bc10c7a13385ccf0b08c1660332f57a07e1f2a8 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 7 Jan 2025 15:34:36 +0100
Subject: [PATCH 11/55] update tab selector indicator automatically on load of
 the new details item

---
 src/app/[locale]/results/page.tsx                     | 6 +++++-
 src/components/app/results/CategoryBar.tsx            | 4 +++-
 src/components/app/results/Details/RelatedResults.tsx | 6 +++++-
 src/components/app/results/ListResults.tsx            | 6 ++++--
 4 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/src/app/[locale]/results/page.tsx b/src/app/[locale]/results/page.tsx
index 5a0f928..cd67949 100644
--- a/src/app/[locale]/results/page.tsx
+++ b/src/app/[locale]/results/page.tsx
@@ -40,7 +40,11 @@ const ResultsComponent = () => {
           ) : null}
 
           {activeCategory && (
-            <ListResults activeCategory={activeCategory} setResultsLoading={setResultsLoading} />
+            <ListResults
+              activeCategory={activeCategory}
+              resultsLoading={resultsLoading}
+              setResultsLoading={setResultsLoading}
+            />
           )}
         </div>
       </>
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index d2bb399..b0c4ef6 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -74,7 +74,8 @@ const CategoryBarComponent = ({
     categories.forEach((cat: Category) =>
       cat.id === currentlyActivecategory ? setActiveCategory(cat) : null
     );
-  }, [currentlyActivecategory, categories, setActiveCategory]);
+    inDetailsView && setActiveCategory(categories[0]);
+  }, [currentlyActivecategory, categories, inDetailsView, setActiveCategory]);
 
   useEffect(() => {
     const updateCategoryCount = async () => {
@@ -95,6 +96,7 @@ const CategoryBarComponent = ({
         setHasSearchError(true);
       } finally {
         setCategoryLoading(false);
+        // console.log("here", categories);
       }
     };
 
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index 1c5228a..f623297 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -30,7 +30,11 @@ const RelatedResults = () => {
           inDetailsView
         />
         {activeCategory && (
-          <ListResults activeCategory={activeCategory} setResultsLoading={setResultsLoading} />
+          <ListResults
+            activeCategory={activeCategory}
+            resultsLoading={resultsLoading}
+            setResultsLoading={setResultsLoading}
+          />
         )}
       </>
 
diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index dfa0581..55701f3 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -15,10 +15,11 @@ import { search, getRorInfo } from "@/utils/apiCall";
 
 type Props = {
   activeCategory: Category;
+  resultsLoading: boolean;
   setResultsLoading: Dispatch<SetStateAction<boolean>>;
 };
 
-const ListResultsComponent = ({ activeCategory, setResultsLoading }: Props) => {
+const ListResultsComponent = ({ activeCategory, resultsLoading, setResultsLoading }: Props) => {
   const t = useTranslations("ListResults");
   const s = useTranslations("Categories");
   const resultParams = useSearchParams();
@@ -60,6 +61,7 @@ const ListResultsComponent = ({ activeCategory, setResultsLoading }: Props) => {
 
   useEffect(() => {
     setPage(0);
+    setSelectedFilters([]);
   }, [activeCategory]);
 
   useEffect(() => {
@@ -108,7 +110,7 @@ const ListResultsComponent = ({ activeCategory, setResultsLoading }: Props) => {
 
   return (
     <>
-      {hasError ? (
+      {resultsLoading ? null : hasError ? (
         <Error />
       ) : (
         <div
-- 
GitLab


From 0b7a7be5b7f28f2f09d18eb684a8e02d6e017663 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 8 Jan 2025 13:01:28 +0100
Subject: [PATCH 12/55] changed atom format to handle routing history, added
 translation for texts related to details view

---
 .../app/results/Details/DetailsItemCard.tsx   | 24 ++++++++++---------
 .../app/results/Details/RelatedResults.tsx    |  7 ++++++
 src/components/app/results/ListResults.tsx    | 12 +++++++---
 .../app/results/ListResults/ResultItem.tsx    |  4 ++--
 src/locales/de.json                           |  3 +++
 src/locales/en.json                           |  3 +++
 src/{state => utils}/atoms.tsx                |  2 +-
 7 files changed, 38 insertions(+), 17 deletions(-)
 rename src/{state => utils}/atoms.tsx (58%)

diff --git a/src/components/app/results/Details/DetailsItemCard.tsx b/src/components/app/results/Details/DetailsItemCard.tsx
index c5f4ca8..ca10382 100644
--- a/src/components/app/results/Details/DetailsItemCard.tsx
+++ b/src/components/app/results/Details/DetailsItemCard.tsx
@@ -1,27 +1,29 @@
 "use client";
+
 import { useAtomValue } from "jotai";
-import React, { useState, useEffect } from "react";
+import { useSearchParams } from "next/navigation";
+import React from "react";
 
-import { detailsItemAtom } from "@/state/atoms";
 import { ResultItem as ResultItemType } from "@/types/types";
+import { detailsItemAtom } from "@/utils/atoms";
 
 import ResultItem from "../ListResults/ResultItem";
 
 const DetailsItemCard = () => {
-  const detailsItemAtomValue: ResultItemType | undefined = useAtomValue(detailsItemAtom);
-  const [detailsItem, setDetailsItem] = useState<ResultItemType | undefined>();
+  const detailsText = useSearchParams().get("detailsText");
+  const detailsItemAtomValue: ResultItemType[] = useAtomValue(detailsItemAtom);
 
-  useEffect(() => {
-    const isResultItem = (
-      detailsItemAtomValue?: ResultItemType
-    ): detailsItemAtomValue is ResultItemType => detailsItemAtomValue !== undefined;
+  const detailsItem = detailsItemAtomValue.filter(
+    (item?: ResultItemType) => item?.name.toLocaleLowerCase() === detailsText?.toLowerCase()
+  )[0];
 
-    if (isResultItem(detailsItemAtomValue)) setDetailsItem(detailsItemAtomValue);
-  }, [detailsItemAtomValue]);
+  const isResultItem = (
+    detailsItemAtomValue?: ResultItemType
+  ): detailsItemAtomValue is ResultItemType => detailsItemAtomValue !== undefined;
 
   return (
     <>
-      {detailsItem ? (
+      {isResultItem(detailsItem) ? (
         <div className="p-4">
           <ResultItem item={detailsItem} idx={detailsItem.id} inDetailsPage />
         </div>
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index f623297..d322c8c 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -1,4 +1,5 @@
 "use client";
+import { useTranslations } from "next-intl";
 import React, { useState } from "react";
 
 import ListResults from "@/components/app/results/ListResults";
@@ -9,6 +10,7 @@ import { Category } from "@/types/types";
 import CategoryBar from "../CategoryBar";
 
 const RelatedResults = () => {
+  const d = useTranslations("DetailsView");
   const [categoryLoading, setCategoryLoading] = useState(true);
   const [resultsLoading, setResultsLoading] = useState(true);
   const [hasBcError, setHasBcError] = useState(false);
@@ -18,6 +20,11 @@ const RelatedResults = () => {
   return (
     <div className="m-4 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-4 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white">
       <>
+        {!categoryLoading && !resultsLoading ? (
+          <p className="text-sm font-semibold text-primary-helmholtz-dunkelblau cursor-default">
+            {d("other_items")}
+          </p>
+        ) : null}
         <CategoryBar
           activeCategory={activeCategory}
           categoryLoading={categoryLoading}
diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index 55701f3..235e851 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -1,5 +1,5 @@
 "use client";
-
+import { useSetAtom } from "jotai";
 import { useSearchParams } from "next/navigation";
 import { useTranslations } from "next-intl";
 import React, { Suspense, useEffect, useState, Dispatch, SetStateAction } from "react";
@@ -12,6 +12,7 @@ import SelectedFiltersBar from "@/components/app/results/ListResults/SelectedFil
 import Error from "@/components/layout/Error";
 import type { Category, FilterEntity, ResultItem as ResultItemType } from "@/types/types";
 import { search, getRorInfo } from "@/utils/apiCall";
+import { detailsItemAtom } from "@/utils/atoms";
 
 type Props = {
   activeCategory: Category;
@@ -22,13 +23,17 @@ type Props = {
 const ListResultsComponent = ({ activeCategory, resultsLoading, setResultsLoading }: Props) => {
   const t = useTranslations("ListResults");
   const s = useTranslations("Categories");
-  const resultParams = useSearchParams();
+
+  const setDetailsItem = useSetAtom(detailsItemAtom);
+
   const [hasError, setHasError] = useState(false);
   const [start, setStart] = useState(0);
   const [results, setResults] = useState<ResultItemType[]>([]);
   const [searchCount, setSearchCount] = useState(0);
   const [availableFilters, setAvailableFilters] = useState<FilterEntity[]>([]);
   const [selectedFilters, setSelectedFilters] = useState<FilterEntity[]>([]);
+
+  const resultParams = useSearchParams();
   const searchText = resultParams.get("searchText") ?? undefined;
   const detailsText = resultParams.get("detailsText") ?? undefined;
   // define this here to make it possible to change later
@@ -62,7 +67,8 @@ const ListResultsComponent = ({ activeCategory, resultsLoading, setResultsLoadin
   useEffect(() => {
     setPage(0);
     setSelectedFilters([]);
-  }, [activeCategory]);
+    !detailsText && setDetailsItem(() => []);
+  }, [detailsText, activeCategory, setDetailsItem]);
 
   useEffect(() => {
     const updateResultList = async () => {
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 8b523f9..4f593b0 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -12,8 +12,8 @@ import Relationships from "@/components/app/results/ListResults/ResultItem/Relat
 import { Link } from "@/i18n";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
-import { detailsItemAtom } from "@/state/atoms";
 import type { Category, ResultItem as ResultItemType } from "@/types/types";
+import { detailsItemAtom } from "@/utils/atoms";
 
 type Props = {
   item: ResultItemType;
@@ -106,7 +106,7 @@ const ResultItem = ({ item, idx, searchText, activeCategory, inDetailsPage }: Pr
   };
 
   const handleDetailSearch = () => {
-    setDetailsItem(() => item);
+    setDetailsItem((prev) => [...prev, ...[item]]);
     router.push(
       `/results/details?category=${activeCategory?.id}${searchText ? `&searchText=${searchText}` : ``}&detailsText=${item.name}`
     );
diff --git a/src/locales/de.json b/src/locales/de.json
index 101963e..8517cc4 100644
--- a/src/locales/de.json
+++ b/src/locales/de.json
@@ -202,5 +202,8 @@
     "automated_decision": "Als verantwortungsbewusstes Unternehmen verzichten wir auf automatische Entscheidungsfindung und Profiling.",
     "amendment_heading": "14. Änderung der Datenschutzerklärung",
     "amendment": "Wir können unsere Datenschutzerklärung von Zeit zu Zeit aktualisieren. Aktualisierungen unserer Datenschutzerklärung werden auf unserer Website veröffentlicht. Alle Änderungen treten mit der Veröffentlichung auf unserer Website in Kraft. Wir empfehlen Ihnen daher, die Website regelmäßig zu besuchen, um sich über mögliche Aktualisierungen zu informieren. Diese Datenschutzerklärung wurde mit dem Datenschutzerklärungs-Generator der externen Datenschutzbeauftragten erstellt, der in Zusammenarbeit mit der RC GmbH, die gebrauchte Notebooks vertreibt, und den Medienrechtlern von WBS-LAW entwickelt wurde."
+  },
+  "DetailsView": {
+    "other_items": "ANDERE ZUGEHÖRIGE ARTIKEL"
   }
 }
diff --git a/src/locales/en.json b/src/locales/en.json
index 0d51403..8013bb9 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -202,5 +202,8 @@
     "automated_decision": "As a responsible company, we do not use automatic decision-making or profiling.",
     "amendment_heading": "14. Amendment of Privacy Statement",
     "amendment": "We may update our Privacy Statement from time to time. Updates of our Privacy Statement will be published on our Website. Any amendments become effective upon publication on our Website. We therefore recommend that you regularly visit the site to keep yourself informed on possible updates. This Privacy Policy has been generated by the Privacy Policy Generator of the External Data Protection Officers that was developed in cooperation with RC GmbH, which sells used notebooks and the Media Law Lawyers from WBS-LAW."
+  },
+  "DetailsView": {
+    "other_items": "OTHER RELATED ITEMS"
   }
 }
diff --git a/src/state/atoms.tsx b/src/utils/atoms.tsx
similarity index 58%
rename from src/state/atoms.tsx
rename to src/utils/atoms.tsx
index 6aade35..5e9c3c5 100644
--- a/src/state/atoms.tsx
+++ b/src/utils/atoms.tsx
@@ -2,4 +2,4 @@ import { atom } from "jotai";
 
 import { ResultItem } from "@/types/types";
 
-export const detailsItemAtom = atom<ResultItem>();
+export const detailsItemAtom = atom<ResultItem[]>([]);
-- 
GitLab


From 6161d49bb8b6baf5f19e0ecf5df18c7c4e501892 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 8 Jan 2025 13:47:12 +0100
Subject: [PATCH 13/55] handle saving only relevant navigations in the router
 stack for smooth back navigations

---
 src/components/app/results/CategoryBar.tsx | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index b0c4ef6..44565b8 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -126,6 +126,7 @@ const CategoryBarComponent = ({
                   : `/results?category=${o.id}${search}`
               }
               shallow
+              replace={!!(inDetailsView && activeCategory?.id !== currentlyActivecategory)}
               onClick={() => setActiveCategory(o)}
               key={idx}
               className={`${
-- 
GitLab


From 6e0d739c062b044372c2e77a64bc2d70e2364020 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 8 Jan 2025 13:54:25 +0100
Subject: [PATCH 14/55] minor divider style bug fix

---
 src/components/app/results/ListResults.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index 235e851..664c3b0 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -124,7 +124,7 @@ const ListResultsComponent = ({ activeCategory, resultsLoading, setResultsLoadin
             availableFilters.length !== 0
               ? "md:divide-x-2 md:divide-primary-helmholtz-hellblau"
               : ""
-          } md:grid md:grid-cols-12 md:min-h-full`}
+          } md:grid md:grid-cols-12`}
         >
           <div
             className={`${
-- 
GitLab


From b1c3262516bbcc49290757e72a3f6dae20a5be31 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 9 Jan 2025 11:41:08 +0100
Subject: [PATCH 15/55] truncate example values in mobile view on search card,
 bug fix with filter component size in mobile view

---
 src/components/app/results/ListResults.tsx | 2 +-
 src/components/layout/Search.tsx           | 2 +-
 src/components/layout/Spinner.tsx          | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index 664c3b0..bda2a05 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -128,7 +128,7 @@ const ListResultsComponent = ({ activeCategory, resultsLoading, setResultsLoadin
         >
           <div
             className={`${
-              availableFilters.length !== 0 ? "md:col-span-4 lg:col-span-3 min-h-full" : "hidden"
+              availableFilters.length !== 0 ? "md:col-span-4 lg:col-span-3 md:min-h-full" : "hidden"
             }  flex flex-col px-4 xl:px-6`}
           >
             <Filters
diff --git a/src/components/layout/Search.tsx b/src/components/layout/Search.tsx
index 3b1252c..2c6d9a7 100644
--- a/src/components/layout/Search.tsx
+++ b/src/components/layout/Search.tsx
@@ -94,7 +94,7 @@ const SearchComponent = ({ exampleTrigger, placeholder }: Props) => {
         </div>
       </form>
 
-      <div className="flex md:basis-11/12 space-x-2 pl-2 pt-3 items-center">
+      <div className="flex md:basis-11/12 space-x-2 pl-2 pt-3 items-center truncate">
         <div className="font-bold text-primary-helmholtz-dunkelblau pr-2">{exampleTrigger}</div>
         <div className="flex flex-wrap gap-x-8 gap-y-2 flex-row md:flex-nowrap md:gap-x-10 md:grow md:justify-between h-5">
           {exampleSearch.map((query, ix) => (
diff --git a/src/components/layout/Spinner.tsx b/src/components/layout/Spinner.tsx
index e06cbfe..b78807f 100644
--- a/src/components/layout/Spinner.tsx
+++ b/src/components/layout/Spinner.tsx
@@ -1,5 +1,5 @@
 const Spinner = () => (
-  <div className="grow flex flex-col p-10 bg-whitesmoke h-full">
+  <div className="grow flex flex-col p-10 pt-5 bg-whitesmoke h-full">
     <svg
       className="m-auto align-middle max-h-20 max-w-20 animate-spin text-secondary-helmholtz-mint"
       xmlns="http://www.w3.org/2000/svg"
-- 
GitLab


From 697770061de7392a246a0a863bd12a378eedae0d Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 14 Jan 2025 13:35:12 +0100
Subject: [PATCH 16/55] title of resultitem card made fully responsive

---
 src/components/app/results/ListResults.tsx    |  3 ++-
 .../app/results/ListResults/ResultItem.tsx    | 21 ++++++++++++++-----
 src/resources/images/svg/RightArrowIcon.tsx   |  2 +-
 3 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/components/app/results/ListResults.tsx b/src/components/app/results/ListResults.tsx
index bda2a05..d58ca94 100644
--- a/src/components/app/results/ListResults.tsx
+++ b/src/components/app/results/ListResults.tsx
@@ -124,7 +124,7 @@ const ListResultsComponent = ({ activeCategory, resultsLoading, setResultsLoadin
             availableFilters.length !== 0
               ? "md:divide-x-2 md:divide-primary-helmholtz-hellblau"
               : ""
-          } md:grid md:grid-cols-12`}
+          } md:grid md:grid-cols-12 overscroll-x-none overflow-x-hidden`}
         >
           <div
             className={`${
@@ -170,6 +170,7 @@ const ListResultsComponent = ({ activeCategory, resultsLoading, setResultsLoadin
                     idx={item.id}
                     activeCategory={activeCategory}
                     searchText={searchText}
+                    associatedToFilters={availableFilters.length !== 0}
                   />
                 ))
               ) : (
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 4f593b0..8da6216 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -21,9 +21,17 @@ type Props = {
   searchText?: string;
   activeCategory?: Category;
   inDetailsPage?: boolean;
+  associatedToFilters: boolean;
 };
 
-const ResultItem = ({ item, idx, searchText, activeCategory, inDetailsPage }: Props) => {
+const ResultItem = ({
+  item,
+  idx,
+  searchText,
+  activeCategory,
+  inDetailsPage,
+  associatedToFilters,
+}: Props) => {
   const setDetailsItem = useSetAtom(detailsItemAtom);
   const router = useRouter();
   const t = useTranslations("ResultItem");
@@ -115,10 +123,10 @@ const ResultItem = ({ item, idx, searchText, activeCategory, inDetailsPage }: Pr
   return (
     <div
       key={idx}
-      className="my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white"
+      className="my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto"
     >
       <button
-        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau h-5`}
+        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau`}
         onClick={handleDetailSearch}
         disabled={inDetailsPage}
       >
@@ -133,9 +141,12 @@ const ResultItem = ({ item, idx, searchText, activeCategory, inDetailsPage }: Pr
             />
           </span>
         ) : null}
-        <div className="font-semibold" rel="noreferrer">
+        <p
+          className={`${associatedToFilters ? "md:basis-10/12" : "md:flex-none lg:line-clamp-none"} ${inDetailsPage ? "line-clamp-none" : ""} basis-10/12 line-clamp-1 flex-1 font-semibold text-left`}
+          rel="noreferrer"
+        >
           {item.name}
-        </div>
+        </p>
         {inDetailsPage ?? <RightArrowIcon />}
       </button>
 
diff --git a/src/resources/images/svg/RightArrowIcon.tsx b/src/resources/images/svg/RightArrowIcon.tsx
index 4c7c156..6a6faad 100644
--- a/src/resources/images/svg/RightArrowIcon.tsx
+++ b/src/resources/images/svg/RightArrowIcon.tsx
@@ -7,7 +7,7 @@ const RightArrowIcon = () => {
       viewBox="0 0 24 24"
       strokeWidth="1.5"
       stroke="currentColor"
-      className="w-5 h-5 p-2"
+      className="w-5 h-5"
     >
       <path
         strokeLinecap="round"
-- 
GitLab


From 28aff05c8412c2fbfb8a5e132092ee15c2a08230 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 14 Jan 2025 16:39:49 +0100
Subject: [PATCH 17/55] made styling of resultitem components a little more
 mobile friendly

---
 .../app/results/ListResults/ResultItem.tsx    | 24 ++++++++++---------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 8da6216..5a09273 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -64,15 +64,17 @@ const ResultItem = ({
 
   const renderLinkItem = (url: string, isEmail = false) =>
     isExternalLink(url) ? (
-      <Link
-        href={isEmail ? `mailto:${url}` : `${url}`}
-        rel="noreferrer"
-        target={isEmail ? "_self" : "_blank"}
-        className="inline-flex gap-x-0.5 text-wrap hover:underline hover:decoration-solid hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau visited:text-primary-helmholtz-dunkelblau h-3"
-      >
-        {url}
-        <ExternalLinkIcon />
-      </Link>
+      <>
+        <Link
+          href={isEmail ? `mailto:${url}` : `${url}`}
+          rel="noreferrer"
+          target={isEmail ? "_self" : "_blank"}
+          className={`${associatedToFilters ? "" : "md:flex-none lg:line-clamp-none"} ${inDetailsPage ? "line-clamp-none" : ""} line-clamp-2 inline-flex text-left gap-x-0.5 hover:underline hover:decoration-solid hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau visited:text-primary-helmholtz-dunkelblau size-auto `}
+        >
+          {url}
+          <ExternalLinkIcon />
+        </Link>
+      </>
     ) : (
       <span className="cursor-default">{url}</span>
     );
@@ -80,7 +82,7 @@ const ResultItem = ({
   const displayLinkItem = (displayItem: string | string[], isEmail = false) =>
     Array.isArray(displayItem)
       ? displayItem.map((url, idx) => (
-          <span key={idx}>
+          <span key={idx} className="">
             {renderLinkItem(url, isEmail)}
             {idx === displayItem.length - 1 ? null : `, `}
           </span>
@@ -157,7 +159,7 @@ const ResultItem = ({
 
       {item.txt_sameAs ? (
         <div className="text-sm">
-          <span className="font-semibold">{s("txt_sameAs")}: </span>
+          <span className="font-semibold ">{s("txt_sameAs")}: </span>
           {displayLinkItem(item.txt_sameAs)}
         </div>
       ) : null}
-- 
GitLab


From d4298ad0a1aaa3d8b2604a5d48b9f54cf950e652 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 16 Jan 2025 13:44:26 +0100
Subject: [PATCH 18/55] default styling for mobile view in results page
 implemented

---
 src/app/[locale]/globals.css                  |  3 ++
 .../app/results/ListResults/ResultItem.tsx    | 52 +++++++++++--------
 2 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/src/app/[locale]/globals.css b/src/app/[locale]/globals.css
index a22dd0d..de8b0ec 100644
--- a/src/app/[locale]/globals.css
+++ b/src/app/[locale]/globals.css
@@ -9,4 +9,7 @@
   #smallScreenSearch {
     @apply m-10 p-10 rounded-lg drop-shadow bg-left-bottom border-2 lg:hidden;
   }
+  .forText {
+    @apply text-ellipsis overflow-x-hidden line-clamp-1 md:overflow-x-visible md:line-clamp-none;
+  }
 }
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 5a09273..a89011b 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -64,17 +64,22 @@ const ResultItem = ({
 
   const renderLinkItem = (url: string, isEmail = false) =>
     isExternalLink(url) ? (
-      <>
-        <Link
-          href={isEmail ? `mailto:${url}` : `${url}`}
-          rel="noreferrer"
-          target={isEmail ? "_self" : "_blank"}
-          className={`${associatedToFilters ? "" : "md:flex-none lg:line-clamp-none"} ${inDetailsPage ? "line-clamp-none" : ""} line-clamp-2 inline-flex text-left gap-x-0.5 hover:underline hover:decoration-solid hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau visited:text-primary-helmholtz-dunkelblau size-auto `}
-        >
-          {url}
+      <Link
+        href={isEmail ? `mailto:${url}` : `${url}`}
+        rel="noreferrer"
+        target={isEmail ? "_self" : "_blank"}
+        className={`${associatedToFilters ? "" : ""} ${inDetailsPage ? "bg-red-500" : "forText w-[98%] inline-block relative md:inline-flex md:w-auto"} 
+         text-left gap-x-0.5 hover:underline hover:decoration-solid
+         hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau 
+         visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau
+        visited:text-primary-helmholtz-dunkelblau 
+        border-2 border-green-800`}
+      >
+        {url}
+        <div className="absolute top-0 right-0 md:static">
           <ExternalLinkIcon />
-        </Link>
-      </>
+        </div>
+      </Link>
     ) : (
       <span className="cursor-default">{url}</span>
     );
@@ -82,10 +87,13 @@ const ResultItem = ({
   const displayLinkItem = (displayItem: string | string[], isEmail = false) =>
     Array.isArray(displayItem)
       ? displayItem.map((url, idx) => (
-          <span key={idx} className="">
+          <div
+            key={idx}
+            className={`${isExternalLink(url) ? "grow" : "grow-0"} items-end border-2 border-blue-600 inline-flex gap-x-1 truncate`}
+          >
             {renderLinkItem(url, isEmail)}
             {idx === displayItem.length - 1 ? null : `, `}
-          </span>
+          </div>
         ))
       : renderLinkItem(displayItem, isEmail);
 
@@ -125,7 +133,7 @@ const ResultItem = ({
   return (
     <div
       key={idx}
-      className="my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto"
+      className="flex flex-col my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto"
     >
       <button
         className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau`}
@@ -144,7 +152,7 @@ const ResultItem = ({
           </span>
         ) : null}
         <p
-          className={`${associatedToFilters ? "md:basis-10/12" : "md:flex-none lg:line-clamp-none"} ${inDetailsPage ? "line-clamp-none" : ""} basis-10/12 line-clamp-1 flex-1 font-semibold text-left`}
+          className={`${associatedToFilters ? "md:basis-10/12" : "lg:flex-none lg:line-clamp-none"} ${inDetailsPage ? "line-clamp-none" : ""} basis-10/12 line-clamp-1 flex-1 font-semibold text-left`}
           rel="noreferrer"
         >
           {item.name}
@@ -152,19 +160,19 @@ const ResultItem = ({
         {inDetailsPage ?? <RightArrowIcon />}
       </button>
 
-      <div className="text-sm">
+      <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
         <span className="font-semibold">{s("txt_identifier")}: </span>
         {displayLinkItem(item.txt_identifier ?? item.id)}
       </div>
 
       {item.txt_sameAs ? (
-        <div className="text-sm">
-          <span className="font-semibold ">{s("txt_sameAs")}: </span>
+        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+          <span className="font-semibold">{s("txt_sameAs")}: </span>
           {displayLinkItem(item.txt_sameAs)}
         </div>
       ) : null}
       {item.txt_email ? (
-        <div className="text-sm">
+        <div className="text-sm ">
           <span className="font-semibold">{s("txt_email")}: </span>
           {displayLinkItem(item.txt_email, true)}
         </div>
@@ -209,13 +217,13 @@ const ResultItem = ({
         </div>
       ) : null}
       {item.txt_license ? (
-        <div className="text-sm">
+        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
           <span className="font-semibold">{s("txt_license")}: </span>
           {displayLinkItem(item.txt_license)}
         </div>
       ) : null}
       {item.txt_url ? (
-        <div className="text-sm">
+        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
           <span className="font-semibold">{s("txt_url")}: </span>
           {displayLinkItem(item.txt_url)}
         </div>
@@ -278,7 +286,7 @@ const ResultItem = ({
           </div>
         ) : null}
         {item.links ? (
-          <div className="text-sm">
+          <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
             <span className="font-semibold">{s("links")}: </span>
             {displayLinkItem(item.links)}
           </div>
@@ -308,7 +316,7 @@ const ResultItem = ({
           </div>
         ) : null}
         {item.wikipedia_url ? (
-          <div className="text-sm">
+          <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
             <span className="font-semibold">{s("wikipedia_url")}: </span>
             {displayLinkItem(item.wikipedia_url)}
           </div>
-- 
GitLab


From 64706db7f9bf2275f03b1972c031d79998e2c12d Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 16 Jan 2025 16:24:01 +0100
Subject: [PATCH 19/55] moderate fixes for styling to scale when dynamic
 filters are present in results view

---
 src/app/[locale]/globals.css                  |  6 ++++-
 .../app/results/ListResults/ResultItem.tsx    | 23 +++++++++++--------
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/src/app/[locale]/globals.css b/src/app/[locale]/globals.css
index de8b0ec..17289e0 100644
--- a/src/app/[locale]/globals.css
+++ b/src/app/[locale]/globals.css
@@ -10,6 +10,10 @@
     @apply m-10 p-10 rounded-lg drop-shadow bg-left-bottom border-2 lg:hidden;
   }
   .forText {
-    @apply text-ellipsis overflow-x-hidden line-clamp-1 md:overflow-x-visible md:line-clamp-none;
+    @apply overflow-clip text-ellipsis;
+  }
+
+  .test {
+    @apply inline-block !important;
   }
 }
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index a89011b..0ccba00 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -68,15 +68,18 @@ const ResultItem = ({
         href={isEmail ? `mailto:${url}` : `${url}`}
         rel="noreferrer"
         target={isEmail ? "_self" : "_blank"}
-        className={`${associatedToFilters ? "" : ""} ${inDetailsPage ? "bg-red-500" : "forText w-[98%] inline-block relative md:inline-flex md:w-auto"} 
-         text-left gap-x-0.5 hover:underline hover:decoration-solid
-         hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau 
-         visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau
-        visited:text-primary-helmholtz-dunkelblau 
-        border-2 border-green-800`}
+        className={`text-left gap-x-0.5 hover:underline hover:decoration-solid
+        hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau 
+        visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau
+      visited:text-primary-helmholtz-dunkelblau 
+        border-2 border-green-800
+        max-w-[98%] inline-block relative truncate md:inline-flex md:w-auto 
+        ${associatedToFilters ? "md:w-20 md:test md:relative md:truncate lg:inline-flex lg:w-auto" : ""} `}
       >
         {url}
-        <div className="absolute top-0 right-0 md:static">
+        <div
+          className={`absolute top-0 right-0 md:static ${associatedToFilters ? "bg-green-500 md:absolute md:top-0 md:right-0 lg:static" : ""} `}
+        >
           <ExternalLinkIcon />
         </div>
       </Link>
@@ -172,7 +175,7 @@ const ResultItem = ({
         </div>
       ) : null}
       {item.txt_email ? (
-        <div className="text-sm ">
+        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
           <span className="font-semibold">{s("txt_email")}: </span>
           {displayLinkItem(item.txt_email, true)}
         </div>
@@ -229,7 +232,7 @@ const ResultItem = ({
         </div>
       ) : null}
       {item.txt_codeRepository ? (
-        <div className="text-sm">
+        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
           <span className="font-semibold">{s("txt_codeRepository")}: </span>
           {displayLinkItem(item.txt_codeRepository)}
         </div>
@@ -280,7 +283,7 @@ const ResultItem = ({
 
       <>
         {item.email_address ? (
-          <div className="text-sm">
+          <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
             <span className="font-semibold">{s("txt_email")}: </span>
             {displayLinkItem(item.email_address)}
           </div>
-- 
GitLab


From d604a2a86f64c130c19ffaec18316b7b7a1c2512 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 20 Jan 2025 12:56:50 +0100
Subject: [PATCH 20/55] intermediate changes to link responsivity

---
 src/app/[locale]/globals.css                          |  6 +++++-
 src/components/app/results/ListResults/ResultItem.tsx | 10 ++++++----
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/src/app/[locale]/globals.css b/src/app/[locale]/globals.css
index 17289e0..e1e105a 100644
--- a/src/app/[locale]/globals.css
+++ b/src/app/[locale]/globals.css
@@ -10,10 +10,14 @@
     @apply m-10 p-10 rounded-lg drop-shadow bg-left-bottom border-2 lg:hidden;
   }
   .forText {
-    @apply overflow-clip text-ellipsis;
+    @apply truncate !important;
   }
 
   .test {
     @apply inline-block !important;
   }
+
+  .noTest {
+    @apply inline-flex !important;
+  }
 }
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 0ccba00..982adeb 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -65,6 +65,7 @@ const ResultItem = ({
   const renderLinkItem = (url: string, isEmail = false) =>
     isExternalLink(url) ? (
       <Link
+        id="external-link"
         href={isEmail ? `mailto:${url}` : `${url}`}
         rel="noreferrer"
         target={isEmail ? "_self" : "_blank"}
@@ -73,18 +74,19 @@ const ResultItem = ({
         visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau
       visited:text-primary-helmholtz-dunkelblau 
         border-2 border-green-800
-        max-w-[98%] inline-block relative truncate md:inline-flex md:w-auto 
-        ${associatedToFilters ? "md:w-20 md:test md:relative md:truncate lg:inline-flex lg:w-auto" : ""} `}
+        max-w-full inline-block relative truncate md:inline-flex md:w-auto 
+        ${associatedToFilters ?? "md:max-w-full md:test md:relative xl:noTest xl:w-auto"} `}
       >
         {url}
         <div
-          className={`absolute top-0 right-0 md:static ${associatedToFilters ? "bg-green-500 md:absolute md:top-0 md:right-0 lg:static" : ""} `}
+          id="external-link-icon-container"
+          className={`absolute top-0 -right-2 md:static ${associatedToFilters ? "bg-green-500 md:absolute md:top-0 md:right-0 xl:static" : ""} `}
         >
           <ExternalLinkIcon />
         </div>
       </Link>
     ) : (
-      <span className="cursor-default">{url}</span>
+      <span className="cursor-default truncate">{url}</span>
     );
 
   const displayLinkItem = (displayItem: string | string[], isEmail = false) =>
-- 
GitLab


From 7e7e442b34016e3b4101020f880bd2c908de8de1 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 20 Jan 2025 14:21:16 +0100
Subject: [PATCH 21/55] simplified styling for links in different views

---
 src/app/[locale]/globals.css                        |  2 +-
 .../app/results/ListResults/ResultItem.tsx          | 13 ++++++-------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/app/[locale]/globals.css b/src/app/[locale]/globals.css
index e1e105a..7ae4a37 100644
--- a/src/app/[locale]/globals.css
+++ b/src/app/[locale]/globals.css
@@ -10,7 +10,7 @@
     @apply m-10 p-10 rounded-lg drop-shadow bg-left-bottom border-2 lg:hidden;
   }
   .forText {
-    @apply truncate !important;
+    @apply overflow-hidden text-ellipsis ;
   }
 
   .test {
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 982adeb..374350e 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -74,16 +74,15 @@ const ResultItem = ({
         visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau
       visited:text-primary-helmholtz-dunkelblau 
         border-2 border-green-800
-        max-w-full inline-block relative truncate md:inline-flex md:w-auto 
-        ${associatedToFilters ?? "md:max-w-full md:test md:relative xl:noTest xl:w-auto"} `}
+        truncate`}
       >
         {url}
-        <div
-          id="external-link-icon-container"
-          className={`absolute top-0 -right-2 md:static ${associatedToFilters ? "bg-green-500 md:absolute md:top-0 md:right-0 xl:static" : ""} `}
+        <span
+          id="external-link-icon-container "
+          className={`inline-flex  ${associatedToFilters ? "bg-green-500 " : ""} `}
         >
           <ExternalLinkIcon />
-        </div>
+        </span>
       </Link>
     ) : (
       <span className="cursor-default truncate">{url}</span>
@@ -157,7 +156,7 @@ const ResultItem = ({
           </span>
         ) : null}
         <p
-          className={`${associatedToFilters ? "md:basis-10/12" : "lg:flex-none lg:line-clamp-none"} ${inDetailsPage ? "line-clamp-none" : ""} basis-10/12 line-clamp-1 flex-1 font-semibold text-left`}
+          className={`${associatedToFilters ? "" : ""} ${inDetailsPage ? "" : ""} truncate font-semibold text-left`}
           rel="noreferrer"
         >
           {item.name}
-- 
GitLab


From 88c31a3219ef0ce0e5edb59c4f0ec748a4a7b853 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 20 Jan 2025 15:01:58 +0100
Subject: [PATCH 22/55] much simplified styling for links and item title in
 results view and details view on all screens

---
 src/app/[locale]/globals.css                  | 11 -------
 .../app/results/ListResults/ResultItem.tsx    | 33 ++++++++-----------
 2 files changed, 14 insertions(+), 30 deletions(-)

diff --git a/src/app/[locale]/globals.css b/src/app/[locale]/globals.css
index 7ae4a37..a22dd0d 100644
--- a/src/app/[locale]/globals.css
+++ b/src/app/[locale]/globals.css
@@ -9,15 +9,4 @@
   #smallScreenSearch {
     @apply m-10 p-10 rounded-lg drop-shadow bg-left-bottom border-2 lg:hidden;
   }
-  .forText {
-    @apply overflow-hidden text-ellipsis ;
-  }
-
-  .test {
-    @apply inline-block !important;
-  }
-
-  .noTest {
-    @apply inline-flex !important;
-  }
 }
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 374350e..85ba38a 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -72,15 +72,10 @@ const ResultItem = ({
         className={`text-left gap-x-0.5 hover:underline hover:decoration-solid
         hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau 
         visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau
-      visited:text-primary-helmholtz-dunkelblau 
-        border-2 border-green-800
-        truncate`}
+      visited:text-primary-helmholtz-dunkelblau truncate`}
       >
         {url}
-        <span
-          id="external-link-icon-container "
-          className={`inline-flex  ${associatedToFilters ? "bg-green-500 " : ""} `}
-        >
+        <span className="inline-flex">
           <ExternalLinkIcon />
         </span>
       </Link>
@@ -93,7 +88,7 @@ const ResultItem = ({
       ? displayItem.map((url, idx) => (
           <div
             key={idx}
-            className={`${isExternalLink(url) ? "grow" : "grow-0"} items-end border-2 border-blue-600 inline-flex gap-x-1 truncate`}
+            className={`${isExternalLink(url) ? "grow" : "grow-0"} items-end inline-flex gap-x-1 truncate`}
           >
             {renderLinkItem(url, isEmail)}
             {idx === displayItem.length - 1 ? null : `, `}
@@ -140,7 +135,7 @@ const ResultItem = ({
       className="flex flex-col my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto"
     >
       <button
-        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau`}
+        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"}`}
         onClick={handleDetailSearch}
         disabled={inDetailsPage}
       >
@@ -156,7 +151,7 @@ const ResultItem = ({
           </span>
         ) : null}
         <p
-          className={`${associatedToFilters ? "" : ""} ${inDetailsPage ? "" : ""} truncate font-semibold text-left`}
+          className={`${inDetailsPage ? "inline-flex" : " truncate"} font-semibold text-left w-[98%] `}
           rel="noreferrer"
         >
           {item.name}
@@ -164,19 +159,19 @@ const ResultItem = ({
         {inDetailsPage ?? <RightArrowIcon />}
       </button>
 
-      <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+      <div className="text-sm inline-flex flex-wrap items-center">
         <span className="font-semibold">{s("txt_identifier")}: </span>
         {displayLinkItem(item.txt_identifier ?? item.id)}
       </div>
 
       {item.txt_sameAs ? (
-        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+        <div className="text-sm inline-flex flex-wrap items-center">
           <span className="font-semibold">{s("txt_sameAs")}: </span>
           {displayLinkItem(item.txt_sameAs)}
         </div>
       ) : null}
       {item.txt_email ? (
-        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+        <div className="text-sm inline-flex flex-wrap items-center">
           <span className="font-semibold">{s("txt_email")}: </span>
           {displayLinkItem(item.txt_email, true)}
         </div>
@@ -221,19 +216,19 @@ const ResultItem = ({
         </div>
       ) : null}
       {item.txt_license ? (
-        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+        <div className="text-sm inline-flex flex-wrap items-center">
           <span className="font-semibold">{s("txt_license")}: </span>
           {displayLinkItem(item.txt_license)}
         </div>
       ) : null}
       {item.txt_url ? (
-        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+        <div className="text-sm inline-flex flex-wrap items-center">
           <span className="font-semibold">{s("txt_url")}: </span>
           {displayLinkItem(item.txt_url)}
         </div>
       ) : null}
       {item.txt_codeRepository ? (
-        <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+        <div className="text-sm inline-flex flex-wrap items-center">
           <span className="font-semibold">{s("txt_codeRepository")}: </span>
           {displayLinkItem(item.txt_codeRepository)}
         </div>
@@ -284,13 +279,13 @@ const ResultItem = ({
 
       <>
         {item.email_address ? (
-          <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+          <div className="text-sm inline-flex flex-wrap items-center">
             <span className="font-semibold">{s("txt_email")}: </span>
             {displayLinkItem(item.email_address)}
           </div>
         ) : null}
         {item.links ? (
-          <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+          <div className="text-sm inline-flex flex-wrap items-center">
             <span className="font-semibold">{s("links")}: </span>
             {displayLinkItem(item.links)}
           </div>
@@ -320,7 +315,7 @@ const ResultItem = ({
           </div>
         ) : null}
         {item.wikipedia_url ? (
-          <div className="text-sm inline-flex flex-wrap items-center border-2 border-yellow-800">
+          <div className="text-sm inline-flex flex-wrap items-center">
             <span className="font-semibold">{s("wikipedia_url")}: </span>
             {displayLinkItem(item.wikipedia_url)}
           </div>
-- 
GitLab


From 656cc9a6dd7c297d924b0d21f0c66b85c1580375 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 20 Jan 2025 15:30:51 +0100
Subject: [PATCH 23/55] truncated relationships text in mobile view

---
 .../app/results/ListResults/ResultItem/Relationships.tsx  | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/components/app/results/ListResults/ResultItem/Relationships.tsx b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
index 5d45ecc..199734b 100644
--- a/src/components/app/results/ListResults/ResultItem/Relationships.tsx
+++ b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
@@ -35,18 +35,18 @@ const Relationships = ({ filteredArr, type }: Props) => {
     <div className="mt-2 cursor-default">
       <span className="font-semibold">{s(`${type.toLowerCase()}`)}: </span>
 
-      <p ref={relRef} className={relShowMore ? "" : "line-clamp-2 "}>
+      <p ref={relRef} className={relShowMore ? "" : "line-clamp-2"}>
         {filteredArr.map((displayItem, idx: number) => {
           const iconArr = INSTITUTE_ROR_LOGOS.filter((o) => o.id === displayItem.id);
           const iconHref = iconArr.pop()?.logo || "";
 
           return (
-            <span key={displayItem.id} className="">
+            <span key={displayItem.id} className="inline-flex items-end">
               <Link
                 href={displayItem.id}
                 rel="noreferrer"
                 target="_blank"
-                className="mx-0.5 leading-loose inline-flex gap-x-0.5 align-middle items-center hover:underline hover:decoration-solid hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau visited:text-primary-helmholtz-dunkelblau"
+                className="mx-0.5 leading-loose inline-flex gap-x-0.5 align-middle hover:underline hover:decoration-solid hover:decoration-primary-helmholtz-hellblau hover:text-primary-helmholtz-hellblau visited:underline visited:decoration-solid visited:decoration-primary-helmholtz-dunkelblau visited:text-primary-helmholtz-dunkelblau"
               >
                 {iconHref ? (
                   <Image
@@ -57,7 +57,7 @@ const Relationships = ({ filteredArr, type }: Props) => {
                     height={16}
                   />
                 ) : null}
-                {displayItem.label}
+                <p className="line-clamp-1">{displayItem.label}</p>
                 <ExternalLinkIcon />
               </Link>
               {idx === filteredArr.length - 1 ? null : `, `}
-- 
GitLab


From c20fffafcff84c93d247f4f603b2ca182be34975 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 22 Jan 2025 16:23:27 +0100
Subject: [PATCH 24/55] increase details items title size and add underline

---
 .../app/results/ListResults/ResultItem.tsx    | 22 +++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 85ba38a..b946d4c 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -135,7 +135,7 @@ const ResultItem = ({
       className="flex flex-col my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto"
     >
       <button
-        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"}`}
+        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"} mb-2`}
         onClick={handleDetailSearch}
         disabled={inDetailsPage}
       >
@@ -151,7 +151,7 @@ const ResultItem = ({
           </span>
         ) : null}
         <p
-          className={`${inDetailsPage ? "inline-flex" : " truncate"} font-semibold text-left w-[98%] `}
+          className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-8 decoration-primary-helmholtz-hellblau" : " truncate"} font-semibold text-left w-[98%] `}
           rel="noreferrer"
         >
           {item.name}
@@ -159,19 +159,19 @@ const ResultItem = ({
         {inDetailsPage ?? <RightArrowIcon />}
       </button>
 
-      <div className="text-sm inline-flex flex-wrap items-center">
+      <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
         <span className="font-semibold">{s("txt_identifier")}: </span>
         {displayLinkItem(item.txt_identifier ?? item.id)}
       </div>
 
       {item.txt_sameAs ? (
-        <div className="text-sm inline-flex flex-wrap items-center">
+        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
           <span className="font-semibold">{s("txt_sameAs")}: </span>
           {displayLinkItem(item.txt_sameAs)}
         </div>
       ) : null}
       {item.txt_email ? (
-        <div className="text-sm inline-flex flex-wrap items-center">
+        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
           <span className="font-semibold">{s("txt_email")}: </span>
           {displayLinkItem(item.txt_email, true)}
         </div>
@@ -216,19 +216,19 @@ const ResultItem = ({
         </div>
       ) : null}
       {item.txt_license ? (
-        <div className="text-sm inline-flex flex-wrap items-center">
+        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
           <span className="font-semibold">{s("txt_license")}: </span>
           {displayLinkItem(item.txt_license)}
         </div>
       ) : null}
       {item.txt_url ? (
-        <div className="text-sm inline-flex flex-wrap items-center">
+        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
           <span className="font-semibold">{s("txt_url")}: </span>
           {displayLinkItem(item.txt_url)}
         </div>
       ) : null}
       {item.txt_codeRepository ? (
-        <div className="text-sm inline-flex flex-wrap items-center">
+        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
           <span className="font-semibold">{s("txt_codeRepository")}: </span>
           {displayLinkItem(item.txt_codeRepository)}
         </div>
@@ -279,13 +279,13 @@ const ResultItem = ({
 
       <>
         {item.email_address ? (
-          <div className="text-sm inline-flex flex-wrap items-center">
+          <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
             <span className="font-semibold">{s("txt_email")}: </span>
             {displayLinkItem(item.email_address)}
           </div>
         ) : null}
         {item.links ? (
-          <div className="text-sm inline-flex flex-wrap items-center">
+          <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
             <span className="font-semibold">{s("links")}: </span>
             {displayLinkItem(item.links)}
           </div>
@@ -315,7 +315,7 @@ const ResultItem = ({
           </div>
         ) : null}
         {item.wikipedia_url ? (
-          <div className="text-sm inline-flex flex-wrap items-center">
+          <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
             <span className="font-semibold">{s("wikipedia_url")}: </span>
             {displayLinkItem(item.wikipedia_url)}
           </div>
-- 
GitLab


From 5275816f45e6eb88b951a4e4d68d9594d6115276 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 22 Jan 2025 17:11:28 +0100
Subject: [PATCH 25/55] minor correction to underline spacing and text in
 details view

---
 src/components/app/results/ListResults/ResultItem.tsx | 4 ++--
 src/locales/en.json                                   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index b946d4c..f9a5549 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -135,7 +135,7 @@ const ResultItem = ({
       className="flex flex-col my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto"
     >
       <button
-        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"} mb-2`}
+        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"} ${inDetailsPage ? "mb-5" : ""}`}
         onClick={handleDetailSearch}
         disabled={inDetailsPage}
       >
@@ -151,7 +151,7 @@ const ResultItem = ({
           </span>
         ) : null}
         <p
-          className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-8 decoration-primary-helmholtz-hellblau" : " truncate"} font-semibold text-left w-[98%] `}
+          className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-[16px] decoration-secondary-helmholtz-mint" : " truncate"} font-semibold text-left w-[98%] `}
           rel="noreferrer"
         >
           {item.name}
diff --git a/src/locales/en.json b/src/locales/en.json
index 8013bb9..6235bc8 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -204,6 +204,6 @@
     "amendment": "We may update our Privacy Statement from time to time. Updates of our Privacy Statement will be published on our Website. Any amendments become effective upon publication on our Website. We therefore recommend that you regularly visit the site to keep yourself informed on possible updates. This Privacy Policy has been generated by the Privacy Policy Generator of the External Data Protection Officers that was developed in cooperation with RC GmbH, which sells used notebooks and the Media Law Lawyers from WBS-LAW."
   },
   "DetailsView": {
-    "other_items": "OTHER RELATED ITEMS"
+    "other_items": "RELATED ENTRIES"
   }
 }
-- 
GitLab


From dad5fdef9c602d8a4a1165a8351f2027d476310b Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 22 Jan 2025 17:11:39 +0100
Subject: [PATCH 26/55] minor correction to underline spacing and text in
 details view

---
 src/components/app/results/ListResults/ResultItem.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index f9a5549..10f33d3 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -151,7 +151,7 @@ const ResultItem = ({
           </span>
         ) : null}
         <p
-          className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-[16px] decoration-secondary-helmholtz-mint" : " truncate"} font-semibold text-left w-[98%] `}
+          className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-[16px] decoration-primary-helmholtz-hellblau" : " truncate"} font-semibold text-left w-[98%] `}
           rel="noreferrer"
         >
           {item.name}
-- 
GitLab


From bb8713c643bd32788036da140a033584cfef12c8 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 17 Feb 2025 13:04:54 +0100
Subject: [PATCH 27/55] review comment fixes related to mistaken absolute path

---
 src/components/app/results/Details/DetailsItemCard.tsx | 3 +--
 src/components/app/results/ListResults/ResultItem.tsx  | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/components/app/results/Details/DetailsItemCard.tsx b/src/components/app/results/Details/DetailsItemCard.tsx
index ca10382..56ab0cd 100644
--- a/src/components/app/results/Details/DetailsItemCard.tsx
+++ b/src/components/app/results/Details/DetailsItemCard.tsx
@@ -4,11 +4,10 @@ import { useAtomValue } from "jotai";
 import { useSearchParams } from "next/navigation";
 import React from "react";
 
+import ResultItem from "@/components/app/results/ListResults/ResultItem";
 import { ResultItem as ResultItemType } from "@/types/types";
 import { detailsItemAtom } from "@/utils/atoms";
 
-import ResultItem from "../ListResults/ResultItem";
-
 const DetailsItemCard = () => {
   const detailsText = useSearchParams().get("detailsText");
   const detailsItemAtomValue: ResultItemType[] = useAtomValue(detailsItemAtom);
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index 10f33d3..c485f1b 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -21,7 +21,7 @@ type Props = {
   searchText?: string;
   activeCategory?: Category;
   inDetailsPage?: boolean;
-  associatedToFilters: boolean;
+  associatedToFilters?: boolean;
 };
 
 const ResultItem = ({
-- 
GitLab


From 620f01d7dcee70d63af55a9725e49ad68034a3f0 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 17 Feb 2025 17:26:20 +0100
Subject: [PATCH 28/55] added all available logo urls and created container to
 display image or large screens

---
 next.config.mjs                               |  97 +++++
 src/app/api/config/config.ts                  |  60 ++-
 .../app/results/ListResults/ResultItem.tsx    | 388 +++++++++---------
 .../ListResults/ResultItem/Relationships.tsx  |   2 +-
 4 files changed, 342 insertions(+), 205 deletions(-)

diff --git a/next.config.mjs b/next.config.mjs
index 0fc7d23..d9d2c22 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -17,12 +17,24 @@ const nextConfig = {
         pathname:
           "/typo3conf/ext/dreipc_hgf/Resources/Public/Frontend/Build/assets/icons/favicons/icon-228x228.png",
       },
+      {
+        protocol: "https",
+        hostname: "www.upload.wikimedia.org",
+        port: "",
+        pathname: "/wikipedia/commons/9/94/Helmholtz_Association's_Logo.svg",
+      },
       {
         protocol: "https",
         hostname: "www.awi.de",
         port: "",
         pathname: "/_assets/978631966794c5093250775de182779d/Images/AWI/favicon.ico",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q536656#/media/File:AWI_Logo_2017.svg",
+      },
       {
         protocol: "https",
         hostname: "www.geomar.de",
@@ -42,54 +54,109 @@ const nextConfig = {
         port: "",
         pathname: "/sites/default/files/favicons/favicon-16x16.png",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q1912019#/media/File:MDC_Logo_V1_RGB_blue.svg",
+      },
       {
         protocol: "https",
         hostname: "www.desy.de",
         port: "",
         pathname: "/++resource++desy/images/desy_logo_3c_web.svg",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q311801#/media/File:Desy_logo_3c_web.svg",
+      },
       {
         protocol: "https",
         hostname: "www.helmholtz-hzi.de",
         port: "",
         pathname: "/_assets/ae8a1fe32f30b295243325c1db1b8058/Icons/Favicons/HZI/favicon-16x16.png",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q1603242#/media/File:Helmholtz-Zentrum_für_Infektionsforschung_GmbH.jpg",
+      },
       {
         protocol: "https",
         hostname: "www.gfz-potsdam.de",
         port: "",
         pathname: "/typo3conf/ext/gfz_www_sitepackage/Resources/Public/Icons/favicon.ico",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q1205654#/media/File:Deutsches-GeoForschungsZentrum-Logo.svg",
+      },
       {
         protocol: "https",
         hostname: "www.helmholtz-berlin.de",
         port: "",
         pathname: "/favicon.ico",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname:
+          "/wiki/Q314578#/media/File:Helmholtz-Zentrum_Berlin_für_Materialien_und_Energie_Logo.svg",
+      },
       {
         protocol: "https",
         hostname: "www.ufz.de",
         port: "",
         pathname: "/static/custom/weblayout/DefaultInternetLayout/img/favicon.ico",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q880999#/media/File:UFZ_Logo_RGB_DE.png",
+      },
       {
         protocol: "https",
         hostname: "www.hzdr.de",
         port: "",
         pathname: "/favicon-16x16.png",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q883545#/media/File:HZDR-LOGO.png",
+      },
       {
         protocol: "https",
         hostname: "www.dlr.de",
         port: "",
         pathname: "/icon.svg",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q157332#/media/File:DLR_Logo.svg",
+      },
       {
         protocol: "https",
         hostname: "www.gsi.de",
         port: "",
         pathname: "/favicon.ico",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q703993#/media/File:GSI_Logo.svg",
+      },
       {
         protocol: "https",
         hostname: "www.helmholtz-munich.de",
@@ -97,18 +164,36 @@ const nextConfig = {
         pathname:
           "/typo3conf/ext/helmholtz_sitepackage/Resources/Public/Icons/Favicons/favicon-16x16.png",
       },
+      {
+        protocol: "https",
+        hostname: "www.upload.wikimedia.org",
+        port: "",
+        pathname: "/wikipedia/commons/5/51/Helmholtz_Zentrum_München_logo.svg",
+      },
       {
         protocol: "https",
         hostname: "www.kit.edu",
         port: "",
         pathname: "/img/intern/favicon.ico",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q309988#/media/File:Logo_KIT.svg",
+      },
       {
         protocol: "https",
         hostname: "www.dkfz.de",
         port: "",
         pathname: "/global/img/favicon.ico",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q449325#/media/File:Deutsches_Krebsforschungszentrum_Logo.svg",
+      },
       {
         protocol: "https",
         hostname: "cispa.de",
@@ -121,12 +206,24 @@ const nextConfig = {
         port: "",
         pathname: "/typo3conf/ext/fe_website/Resources/Public/AppIcons/favicon-16x16.png",
       },
+      {
+        protocol: "https",
+        hostname: "www.wikidata.org",
+        port: "",
+        pathname: "/wiki/Q1206136#/media/File:DZNE_Logo_CMYK.svg",
+      },
       {
         protocol: "https",
         hostname: "www.fz-juelich.de",
         port: "",
         pathname: "/icon.svg",
       },
+      {
+        protocol: "https",
+        hostname: "www.upload.wikimedia.org",
+        port: "",
+        pathname: "/wikipedia/commons/4/40/Logo_des_Forschungszentrums_Jülich_seit_2018.svg",
+      },
     ],
   },
 };
diff --git a/src/app/api/config/config.ts b/src/app/api/config/config.ts
index b1561db..e588572 100644
--- a/src/app/api/config/config.ts
+++ b/src/app/api/config/config.ts
@@ -252,79 +252,101 @@ export const INSTITUTE_ROR_LOGOS = [
   // Helmholtz Association
   {
     id: "https://ror.org/0281dp749",
-    logo: "https://www.helmholtz.de/typo3conf/ext/dreipc_hgf/Resources/Public/Frontend/Build/assets/icons/favicons/icon-228x228.png",
+    favicon:
+      "https://www.helmholtz.de/typo3conf/ext/dreipc_hgf/Resources/Public/Frontend/Build/assets/icons/favicons/icon-228x228.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/9/94/Helmholtz_Association%27s_Logo.svg",
   },
   // 18 Helmholtz Centers
   {
     id: "https://ror.org/02h2x0161",
-    logo: "https://www.geomar.de/typo3conf/ext/geomar_provider/Resources/Public/Graphics/favicon/favicon-16x16.png",
+    favicon:
+      "https://www.geomar.de/typo3conf/ext/geomar_provider/Resources/Public/Graphics/favicon/favicon-16x16.png",
   },
   {
     id: "https://ror.org/03qjp1d79",
-    logo: "https://hereon.de/favicon-16x16.png",
+    favicon: "https://hereon.de/favicon-16x16.png",
   },
   {
     id: "https://ror.org/04p5ggc03",
-    logo: "https://www.mdc-berlin.de/sites/default/files/favicons/favicon-16x16.png",
+    favicon: "https://www.mdc-berlin.de/sites/default/files/favicons/favicon-16x16.png",
+    logo: "https://www.wikidata.org/wiki/Q1912019#/media/File:MDC_Logo_V1_RGB_blue.svg",
   },
   {
     id: "https://ror.org/01js2sh04",
-    logo: "https://www.desy.de/++resource++desy/images/desy_logo_3c_web.svg",
+    favicon: "https://www.desy.de/++resource++desy/images/desy_logo_3c_web.svg",
+    logo: "https://www.wikidata.org/wiki/Q311801#/media/File:Desy_logo_3c_web.svg",
   },
   {
     id: "https://ror.org/032e6b942",
-    logo: "https://www.awi.de/_assets/978631966794c5093250775de182779d/Images/AWI/favicon.ico",
+    favicon: "https://www.awi.de/_assets/978631966794c5093250775de182779d/Images/AWI/favicon.ico",
+    logo: "https://www.wikidata.org/wiki/Q536656#/media/File:AWI_Logo_2017.svg",
   },
   {
     id: "https://ror.org/03d0p2685",
-    logo: "https://www.helmholtz-hzi.de/_assets/ae8a1fe32f30b295243325c1db1b8058/Icons/Favicons/HZI/favicon-16x16.png",
+    favicon:
+      "https://www.helmholtz-hzi.de/_assets/ae8a1fe32f30b295243325c1db1b8058/Icons/Favicons/HZI/favicon-16x16.png",
+    logo: "https://www.wikidata.org/wiki/Q1603242#/media/File:Helmholtz-Zentrum_f%C3%BCr_Infektionsforschung_GmbH.jpg",
   },
   {
     id: "https://ror.org/04z8jg394",
-    logo: "https://www.gfz-potsdam.de/typo3conf/ext/gfz_www_sitepackage/Resources/Public/Icons/favicon.ico",
+    favicon:
+      "https://www.gfz-potsdam.de/typo3conf/ext/gfz_www_sitepackage/Resources/Public/Icons/favicon.ico",
+    logo: "https://www.wikidata.org/wiki/Q1205654#/media/File:Deutsches-GeoForschungsZentrum-Logo.svg",
   },
   {
     id: "https://ror.org/02aj13c28",
-    logo: "https://www.helmholtz-berlin.de/favicon.ico",
+    favicon: "https://www.helmholtz-berlin.de/favicon.ico",
+    logo: "https://www.wikidata.org/wiki/Q314578#/media/File:Helmholtz-Zentrum_Berlin_f%C3%BCr_Materialien_und_Energie_Logo.svg",
   },
   {
     id: "https://ror.org/000h6jb29",
-    logo: "https://www.ufz.de/static/custom/weblayout/DefaultInternetLayout/img/favicon.ico",
+    favicon: "https://www.ufz.de/static/custom/weblayout/DefaultInternetLayout/img/favicon.ico",
+    logo: "https://www.wikidata.org/wiki/Q880999#/media/File:UFZ_Logo_RGB_DE.png",
   },
   {
     id: "https://ror.org/01zy2cs03",
-    logo: "https://www.hzdr.de/favicon-16x16.png",
+    favicon: "https://www.hzdr.de/favicon-16x16.png",
+    logo: "https://www.wikidata.org/wiki/Q883545#/media/File:HZDR-LOGO.png",
   },
   {
     id: "https://ror.org/04bwf3e34",
-    logo: "https://www.dlr.de/icon.svg",
+    favicon: "https://www.dlr.de/icon.svg",
+    logo: "https://www.wikidata.org/wiki/Q157332#/media/File:DLR_Logo.svg",
   },
   {
     id: "https://ror.org/02k8cbn47",
-    logo: "https://www.gsi.de/favicon.ico",
+    favicon: "https://www.gsi.de/favicon.ico",
+    logo: "https://www.wikidata.org/wiki/Q703993#/media/File:GSI_Logo.svg",
   },
   {
     id: "https://ror.org/00cfam450",
-    logo: "https://www.helmholtz-munich.de/typo3conf/ext/helmholtz_sitepackage/Resources/Public/Icons/Favicons/favicon-16x16.png",
+    favicon:
+      "https://www.helmholtz-munich.de/typo3conf/ext/helmholtz_sitepackage/Resources/Public/Icons/Favicons/favicon-16x16.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/5/51/Helmholtz_Zentrum_M%C3%BCnchen_logo.svg",
   },
   {
     id: "https://ror.org/04t3en479",
-    logo: "https://www.kit.edu/img/intern/favicon.ico",
+    favicon: "https://www.kit.edu/img/intern/favicon.ico",
+    logo: "https://www.wikidata.org/wiki/Q309988#/media/File:Logo_KIT.svg",
   },
   {
     id: "https://ror.org/04cdgtt98",
-    logo: "https://www.dkfz.de/global/img/favicon.ico",
+    favicon: "https://www.dkfz.de/global/img/favicon.ico",
+    logo: "https://www.wikidata.org/wiki/Q449325#/media/File:Deutsches_Krebsforschungszentrum_Logo.svg",
   },
   {
     id: "https://ror.org/02njgxr09",
-    logo: "https://cispa.de/images/cispa-logo-on-bright.svg",
+    favicon: "https://cispa.de/images/cispa-logo-on-bright.svg",
   },
   {
     id: "https://ror.org/043j0f473",
-    logo: "https://www.dzne.de/typo3conf/ext/fe_website/Resources/Public/AppIcons/favicon-16x16.png",
+    favicon:
+      "https://www.dzne.de/typo3conf/ext/fe_website/Resources/Public/AppIcons/favicon-16x16.png",
+    logo: "https://www.wikidata.org/wiki/Q1206136#/media/File:DZNE_Logo_CMYK.svg",
   },
   {
     id: "https://ror.org/02nv7yv05",
-    logo: "https://www.fz-juelich.de/icon.svg",
+    favicon: "https://www.fz-juelich.de/icon.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/4/40/Logo_des_Forschungszentrums_J%C3%BClich_seit_2018.svg",
   },
 ];
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index c485f1b..cca4391 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -41,6 +41,7 @@ const ResultItem = ({
   const [descShowMore, setDescShowMore] = useState(false);
   const [descShowReadMore, setDescShowReadMore] = useState(false);
   const [titleIconHref, setTitleIconHref] = useState<string>("");
+  const [logoHref, setLogoHref] = useState<string>("");
 
   useEffect(() => {
     const element = descRef.current;
@@ -55,8 +56,10 @@ const ResultItem = ({
       }
     }
 
-    const iconArr = INSTITUTE_ROR_LOGOS.filter((o) => o.id === item.id);
-    setTitleIconHref(iconArr.pop()?.logo || "");
+    const iconArr = INSTITUTE_ROR_LOGOS.filter((o) => o.id === item.id).pop();
+    console.log(iconArr);
+    setTitleIconHref(iconArr?.favicon || "");
+    setLogoHref(iconArr?.logo || "");
   }, [item]);
 
   const displayTextItem = (displayItem: string | string[]) =>
@@ -131,218 +134,233 @@ const ResultItem = ({
 
   return (
     <div
-      key={idx}
-      className="flex flex-col my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 px-5 py-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto"
+      className={`flex ${inDetailsPage && logoHref !== "" ? "" : "flex-col"}  my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 p-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto`}
     >
-      <button
-        className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"} ${inDetailsPage ? "mb-5" : ""}`}
-        onClick={handleDetailSearch}
-        disabled={inDetailsPage}
+      <div
+        className={`${inDetailsPage && logoHref !== "" ? "border-2 border-red-400 space-y-2 p-5 mt-2 basis-1/3" : "hidden"}`}
       >
-        {titleIconHref ? (
-          <span className="mr-1">
-            <Image
-              src={titleIconHref}
-              className="object-contain w-5 h-5"
-              alt="Institute icon"
-              width={16}
-              height={16}
-            />
-          </span>
-        ) : null}
-        <p
-          className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-[16px] decoration-primary-helmholtz-hellblau" : " truncate"} font-semibold text-left w-[98%] `}
-          rel="noreferrer"
-        >
-          {item.name}
-        </p>
-        {inDetailsPage ?? <RightArrowIcon />}
-      </button>
-
-      <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-        <span className="font-semibold">{s("txt_identifier")}: </span>
-        {displayLinkItem(item.txt_identifier ?? item.id)}
+        <Image
+          src={logoHref}
+          className="object-contain w-20 h-20"
+          alt="Institute logo"
+          width={80}
+          height={80}
+        />
       </div>
-
-      {item.txt_sameAs ? (
-        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-          <span className="font-semibold">{s("txt_sameAs")}: </span>
-          {displayLinkItem(item.txt_sameAs)}
-        </div>
-      ) : null}
-      {item.txt_email ? (
-        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-          <span className="font-semibold">{s("txt_email")}: </span>
-          {displayLinkItem(item.txt_email, true)}
-        </div>
-      ) : null}
-      {item.txt_affiliation ? (
-        <div className="text-sm">
-          <span className="font-semibold">{s("txt_affiliation")}: </span>
-          {displayTextItem(item.txt_affiliation)}
-        </div>
-      ) : null}
-      {item.txt_author ? (
-        <div
-          className="text-sm truncate max-h-full cursor-default"
-          title={displayTextItem(item.txt_author)}
-        >
-          <span className="font-semibold">{s("txt_author")}: </span>
-          {displayTextItem(item.txt_author)}
-        </div>
-      ) : null}
-      {item.txt_creator ? (
-        <div
-          className="text-sm truncate max-h-full cursor-default"
-          title={displayTextItem(item.txt_creator)}
-        >
-          <span className="font-semibold">{s("txt_creator")}: </span>
-          {displayTextItem(item.txt_creator)}
-        </div>
-      ) : null}
-      {item.txt_contributor ? (
-        <div
-          className="text-sm truncate max-h-full cursor-default"
-          title={displayTextItem(item.txt_contributor)}
+      <div
+        key={idx}
+        className={`flex flex-col ${inDetailsPage && logoHref !== "" ? "basis-2/3" : ""} my-2 space-y-2 p-5 border-2 border-red-500`}
+      >
+        <button
+          className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"} ${inDetailsPage ? "mb-5" : ""}`}
+          onClick={handleDetailSearch}
+          disabled={inDetailsPage}
         >
-          <span className="font-semibold">{s("txt_contributor")}: </span>
-          {displayTextItem(item.txt_contributor)}
-        </div>
-      ) : null}
-      {item.txt_version ? (
-        <div className="text-sm cursor-default">
-          <span className="font-semibold">{s("txt_version")}: </span>
-          {displayTextItem(item.txt_version)}
-        </div>
-      ) : null}
-      {item.txt_license ? (
-        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-          <span className="font-semibold">{s("txt_license")}: </span>
-          {displayLinkItem(item.txt_license)}
-        </div>
-      ) : null}
-      {item.txt_url ? (
-        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-          <span className="font-semibold">{s("txt_url")}: </span>
-          {displayLinkItem(item.txt_url)}
-        </div>
-      ) : null}
-      {item.txt_codeRepository ? (
-        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-          <span className="font-semibold">{s("txt_codeRepository")}: </span>
-          {displayLinkItem(item.txt_codeRepository)}
-        </div>
-      ) : null}
-      {item.txt_provider ? (
-        <div className="text-sm cursor-default">
-          <span className="font-semibold">{s("txt_provider")}: </span>
-          {displayTextItem(item.txt_provider)}
-        </div>
-      ) : null}
-      {item.txt_publisher ? (
-        <div className="text-sm cursor-default">
-          <span className="font-semibold">{s("txt_publisher")}: </span>
-          {displayTextItem(item.txt_publisher)}
-        </div>
-      ) : null}
-      {item.txt_includedInDataCatalog ? (
-        <div className="text-sm cursor-default">
-          <span className="font-semibold">{s("txt_includedInDataCatalog")}: </span>
-          {displayTextItem(item.txt_includedInDataCatalog)}
-        </div>
-      ) : null}
-      {item.txt_keywords ? (
-        <div className="flex flex-wrap space-x-1 space-y-1 text-sm cursor-default">
-          <span className="pt-3 font-semibold">{s("txt_keywords")}: </span>
-          {displayKeywords(item.txt_keywords)}
-        </div>
-      ) : null}
-      {item.description ? (
-        <div className="text-sm">
-          <span className="font-semibold">{s("description")}: </span>
+          {titleIconHref ? (
+            <span className="mr-1">
+              <Image
+                src={titleIconHref}
+                className="object-contain w-5 h-5"
+                alt="Institute icon"
+                width={16}
+                height={16}
+              />
+            </span>
+          ) : null}
           <p
-            ref={descRef}
-            className={descShowMore ? "cursor-default" : "line-clamp-2 cursor-default"}
+            className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-[16px] decoration-primary-helmholtz-hellblau" : " truncate"} font-semibold text-left w-[98%] `}
+            rel="noreferrer"
           >
-            {item.description}
+            {item.name}
           </p>
-          {descShowReadMore ? (
-            <button
-              className="py-0.75 float-right rounded-full border-[1px] border-secondary-helmholtz-mint px-2 text-xs hover:border-primary-helmholtz-hellblau"
-              onClick={() => setDescShowMore(!descShowMore)}
-            >
-              {descShowMore ? t("show_less") : t("show_more")}
-            </button>
-          ) : null}
+          {inDetailsPage ?? <RightArrowIcon />}
+        </button>
+
+        <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
+          <span className="font-semibold">{s("txt_identifier")}: </span>
+          {displayLinkItem(item.txt_identifier ?? item.id)}
         </div>
-      ) : null}
 
-      <>
-        {item.email_address ? (
+        {item.txt_sameAs ? (
           <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-            <span className="font-semibold">{s("txt_email")}: </span>
-            {displayLinkItem(item.email_address)}
+            <span className="font-semibold">{s("txt_sameAs")}: </span>
+            {displayLinkItem(item.txt_sameAs)}
           </div>
         ) : null}
-        {item.links ? (
+        {item.txt_email ? (
           <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-            <span className="font-semibold">{s("links")}: </span>
-            {displayLinkItem(item.links)}
+            <span className="font-semibold">{s("txt_email")}: </span>
+            {displayLinkItem(item.txt_email, true)}
           </div>
         ) : null}
-        {item.status ? (
-          <div className="text-sm capitalize">
-            <span className="font-semibold">{s("status")}: </span>
-            {displayTextItem(item.status)}
+        {item.txt_affiliation ? (
+          <div className="text-sm">
+            <span className="font-semibold">{s("txt_affiliation")}: </span>
+            {displayTextItem(item.txt_affiliation)}
           </div>
         ) : null}
-        {item.established ? (
-          <div className="text-sm">
-            <span className="font-semibold">{s("established")}: </span>
-            {displayTextItem(item.established.toString())}
+        {item.txt_author ? (
+          <div
+            className="text-sm truncate max-h-full cursor-default"
+            title={displayTextItem(item.txt_author)}
+          >
+            <span className="font-semibold">{s("txt_author")}: </span>
+            {displayTextItem(item.txt_author)}
           </div>
         ) : null}
-        {item.acronyms && item.acronyms.length > 0 ? (
-          <div className="text-sm">
-            <span className="font-semibold">{s("acronyms")}: </span>
-            {displayTextItem(item.acronyms)}
+        {item.txt_creator ? (
+          <div
+            className="text-sm truncate max-h-full cursor-default"
+            title={displayTextItem(item.txt_creator)}
+          >
+            <span className="font-semibold">{s("txt_creator")}: </span>
+            {displayTextItem(item.txt_creator)}
           </div>
         ) : null}
-        {item.types && item.types.length > 0 ? (
-          <div className="text-sm">
-            <span className="font-semibold">{s("types")}: </span>
-            {displayTextItem(item.types)}
+        {item.txt_contributor ? (
+          <div
+            className="text-sm truncate max-h-full cursor-default"
+            title={displayTextItem(item.txt_contributor)}
+          >
+            <span className="font-semibold">{s("txt_contributor")}: </span>
+            {displayTextItem(item.txt_contributor)}
+          </div>
+        ) : null}
+        {item.txt_version ? (
+          <div className="text-sm cursor-default">
+            <span className="font-semibold">{s("txt_version")}: </span>
+            {displayTextItem(item.txt_version)}
           </div>
         ) : null}
-        {item.wikipedia_url ? (
+        {item.txt_license ? (
           <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
-            <span className="font-semibold">{s("wikipedia_url")}: </span>
-            {displayLinkItem(item.wikipedia_url)}
+            <span className="font-semibold">{s("txt_license")}: </span>
+            {displayLinkItem(item.txt_license)}
           </div>
         ) : null}
-        {item.relationships && item.relationships.length > 0 ? (
-          <div className="text-sm ">
-            <div className="font-semibold">{s("relationships")}:</div>
-            <div className="flex flex-col pl-8 text-sm">
-              {displayRelationships(item.relationships, "Parent")}
-              {displayRelationships(item.relationships, "Child")}
-              {displayRelationships(item.relationships, "Related")}
-            </div>
+        {item.txt_url ? (
+          <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
+            <span className="font-semibold">{s("txt_url")}: </span>
+            {displayLinkItem(item.txt_url)}
+          </div>
+        ) : null}
+        {item.txt_codeRepository ? (
+          <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
+            <span className="font-semibold">{s("txt_codeRepository")}: </span>
+            {displayLinkItem(item.txt_codeRepository)}
+          </div>
+        ) : null}
+        {item.txt_provider ? (
+          <div className="text-sm cursor-default">
+            <span className="font-semibold">{s("txt_provider")}: </span>
+            {displayTextItem(item.txt_provider)}
+          </div>
+        ) : null}
+        {item.txt_publisher ? (
+          <div className="text-sm cursor-default">
+            <span className="font-semibold">{s("txt_publisher")}: </span>
+            {displayTextItem(item.txt_publisher)}
+          </div>
+        ) : null}
+        {item.txt_includedInDataCatalog ? (
+          <div className="text-sm cursor-default">
+            <span className="font-semibold">{s("txt_includedInDataCatalog")}: </span>
+            {displayTextItem(item.txt_includedInDataCatalog)}
+          </div>
+        ) : null}
+        {item.txt_keywords ? (
+          <div className="flex flex-wrap space-x-1 space-y-1 text-sm cursor-default">
+            <span className="pt-3 font-semibold">{s("txt_keywords")}: </span>
+            {displayKeywords(item.txt_keywords)}
+          </div>
+        ) : null}
+        {item.description ? (
+          <div className="text-sm">
+            <span className="font-semibold">{s("description")}: </span>
+            <p
+              ref={descRef}
+              className={descShowMore ? "cursor-default" : "line-clamp-2 cursor-default"}
+            >
+              {item.description}
+            </p>
+            {descShowReadMore ? (
+              <button
+                className="py-0.75 float-right rounded-full border-[1px] border-secondary-helmholtz-mint px-2 text-xs hover:border-primary-helmholtz-hellblau"
+                onClick={() => setDescShowMore(!descShowMore)}
+              >
+                {descShowMore ? t("show_less") : t("show_more")}
+              </button>
+            ) : null}
           </div>
         ) : null}
-      </>
 
-      <div className="place-content-center pt-6">
-        <ExternalLink
-          key={item.id}
-          href={`/api/source?id=${encodeURIComponent(item.id)}`}
-          className="text-xs hover:underline"
-        >
-          <span className="inline-flex gap-x-1 h-3">
-            {t("view_source")}
-            <ExternalLinkIcon />
-          </span>
-        </ExternalLink>
+        <>
+          {item.email_address ? (
+            <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
+              <span className="font-semibold">{s("txt_email")}: </span>
+              {displayLinkItem(item.email_address)}
+            </div>
+          ) : null}
+          {item.links ? (
+            <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
+              <span className="font-semibold">{s("links")}: </span>
+              {displayLinkItem(item.links)}
+            </div>
+          ) : null}
+          {item.status ? (
+            <div className="text-sm capitalize">
+              <span className="font-semibold">{s("status")}: </span>
+              {displayTextItem(item.status)}
+            </div>
+          ) : null}
+          {item.established ? (
+            <div className="text-sm">
+              <span className="font-semibold">{s("established")}: </span>
+              {displayTextItem(item.established.toString())}
+            </div>
+          ) : null}
+          {item.acronyms && item.acronyms.length > 0 ? (
+            <div className="text-sm">
+              <span className="font-semibold">{s("acronyms")}: </span>
+              {displayTextItem(item.acronyms)}
+            </div>
+          ) : null}
+          {item.types && item.types.length > 0 ? (
+            <div className="text-sm">
+              <span className="font-semibold">{s("types")}: </span>
+              {displayTextItem(item.types)}
+            </div>
+          ) : null}
+          {item.wikipedia_url ? (
+            <div className="text-sm inline-flex flex-wrap items-center gap-x-1">
+              <span className="font-semibold">{s("wikipedia_url")}: </span>
+              {displayLinkItem(item.wikipedia_url)}
+            </div>
+          ) : null}
+          {item.relationships && item.relationships.length > 0 ? (
+            <div className="text-sm ">
+              <div className="font-semibold">{s("relationships")}:</div>
+              <div className="flex flex-col pl-8 text-sm">
+                {displayRelationships(item.relationships, "Parent")}
+                {displayRelationships(item.relationships, "Child")}
+                {displayRelationships(item.relationships, "Related")}
+              </div>
+            </div>
+          ) : null}
+        </>
+
+        <div className="place-content-center pt-6">
+          <ExternalLink
+            key={item.id}
+            href={`/api/source?id=${encodeURIComponent(item.id)}`}
+            className="text-xs hover:underline"
+          >
+            <span className="inline-flex gap-x-1 h-3">
+              {t("view_source")}
+              <ExternalLinkIcon />
+            </span>
+          </ExternalLink>
+        </div>
       </div>
     </div>
   );
diff --git a/src/components/app/results/ListResults/ResultItem/Relationships.tsx b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
index 199734b..e813e47 100644
--- a/src/components/app/results/ListResults/ResultItem/Relationships.tsx
+++ b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
@@ -38,7 +38,7 @@ const Relationships = ({ filteredArr, type }: Props) => {
       <p ref={relRef} className={relShowMore ? "" : "line-clamp-2"}>
         {filteredArr.map((displayItem, idx: number) => {
           const iconArr = INSTITUTE_ROR_LOGOS.filter((o) => o.id === displayItem.id);
-          const iconHref = iconArr.pop()?.logo || "";
+          const iconHref = iconArr.pop()?.favicon || "";
 
           return (
             <span key={displayItem.id} className="inline-flex items-end">
-- 
GitLab


From 8241310f7343adff3b096edea853fe6b5ff76b9e Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 18 Feb 2025 12:48:04 +0100
Subject: [PATCH 29/55] updated urls for logos from wikimedia that actually
 work

---
 next.config.mjs                               | 48 +++++++++----------
 src/app/api/config/config.ts                  | 12 ++---
 .../app/results/ListResults/ResultItem.tsx    | 28 +++++------
 3 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/next.config.mjs b/next.config.mjs
index d9d2c22..4b7fd1e 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -56,9 +56,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q1912019#/media/File:MDC_Logo_V1_RGB_blue.svg",
+        pathname: "/wikipedia/commons/3/3f/MDC_Logo_V1_RGB_blue.svg",
       },
       {
         protocol: "https",
@@ -68,9 +68,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q311801#/media/File:Desy_logo_3c_web.svg",
+        pathname: "/wikipedia/commons/5/55/Desy_logo_3c_web.svg",
       },
       {
         protocol: "https",
@@ -80,9 +80,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q1603242#/media/File:Helmholtz-Zentrum_für_Infektionsforschung_GmbH.jpg",
+        pathname: "/wikipedia/commons/c/cd/Helmholtz-Zentrum_für_Infektionsforschung_GmbH.jpg",
       },
       {
         protocol: "https",
@@ -92,9 +92,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q1205654#/media/File:Deutsches-GeoForschungsZentrum-Logo.svg",
+        pathname: "/wikipedia/commons/8/86/Deutsches-GeoForschungsZentrum-Logo.svg",
       },
       {
         protocol: "https",
@@ -104,10 +104,10 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
         pathname:
-          "/wiki/Q314578#/media/File:Helmholtz-Zentrum_Berlin_für_Materialien_und_Energie_Logo.svg",
+          "/wikipedia/commons/6/6b/Helmholtz-Zentrum_Berlin_für_Materialien_und_Energie_Logo.svg",
       },
       {
         protocol: "https",
@@ -117,9 +117,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q880999#/media/File:UFZ_Logo_RGB_DE.png",
+        pathname: "/wikipedia/commons/e/ed/UFZ_Logo_RGB_DE.png",
       },
       {
         protocol: "https",
@@ -129,9 +129,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q883545#/media/File:HZDR-LOGO.png",
+        pathname: "/wikipedia/commons/e/e5/HZDR-LOGO.png",
       },
       {
         protocol: "https",
@@ -141,9 +141,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q157332#/media/File:DLR_Logo.svg",
+        pathname: "/wikipedia/commons/f/f5/DLR_Logo.svg",
       },
       {
         protocol: "https",
@@ -153,9 +153,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q703993#/media/File:GSI_Logo.svg",
+        pathname: "/wikipedia/commons/6/6f/GSI_Logo.svg",
       },
       {
         protocol: "https",
@@ -178,9 +178,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q309988#/media/File:Logo_KIT.svg",
+        pathname: "/wikipedia/commons/3/3a/Logo_KIT.svg",
       },
       {
         protocol: "https",
@@ -190,9 +190,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q449325#/media/File:Deutsches_Krebsforschungszentrum_Logo.svg",
+        pathname: "/wikipedia/commons/d/d9/Deutsches_Krebsforschungszentrum_Logo.svg",
       },
       {
         protocol: "https",
@@ -208,9 +208,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q1206136#/media/File:DZNE_Logo_CMYK.svg",
+        pathname: "/wikipedia/commons/2/26/DZNE_Logo_CMYK.svg",
       },
       {
         protocol: "https",
diff --git a/src/app/api/config/config.ts b/src/app/api/config/config.ts
index e588572..da4d5e3 100644
--- a/src/app/api/config/config.ts
+++ b/src/app/api/config/config.ts
@@ -269,12 +269,12 @@ export const INSTITUTE_ROR_LOGOS = [
   {
     id: "https://ror.org/04p5ggc03",
     favicon: "https://www.mdc-berlin.de/sites/default/files/favicons/favicon-16x16.png",
-    logo: "https://www.wikidata.org/wiki/Q1912019#/media/File:MDC_Logo_V1_RGB_blue.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/3/3f/MDC_Logo_V1_RGB_blue.svg",
   },
   {
     id: "https://ror.org/01js2sh04",
     favicon: "https://www.desy.de/++resource++desy/images/desy_logo_3c_web.svg",
-    logo: "https://www.wikidata.org/wiki/Q311801#/media/File:Desy_logo_3c_web.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/5/55/Desy_logo_3c_web.svg",
   },
   {
     id: "https://ror.org/032e6b942",
@@ -285,23 +285,23 @@ export const INSTITUTE_ROR_LOGOS = [
     id: "https://ror.org/03d0p2685",
     favicon:
       "https://www.helmholtz-hzi.de/_assets/ae8a1fe32f30b295243325c1db1b8058/Icons/Favicons/HZI/favicon-16x16.png",
-    logo: "https://www.wikidata.org/wiki/Q1603242#/media/File:Helmholtz-Zentrum_f%C3%BCr_Infektionsforschung_GmbH.jpg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/c/cd/Helmholtz-Zentrum_f%C3%BCr_Infektionsforschung_GmbH.jpg",
   },
   {
     id: "https://ror.org/04z8jg394",
     favicon:
       "https://www.gfz-potsdam.de/typo3conf/ext/gfz_www_sitepackage/Resources/Public/Icons/favicon.ico",
-    logo: "https://www.wikidata.org/wiki/Q1205654#/media/File:Deutsches-GeoForschungsZentrum-Logo.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/8/86/Deutsches-GeoForschungsZentrum-Logo.svg",
   },
   {
     id: "https://ror.org/02aj13c28",
     favicon: "https://www.helmholtz-berlin.de/favicon.ico",
-    logo: "https://www.wikidata.org/wiki/Q314578#/media/File:Helmholtz-Zentrum_Berlin_f%C3%BCr_Materialien_und_Energie_Logo.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/6/6b/Helmholtz-Zentrum_Berlin_f%C3%BCr_Materialien_und_Energie_Logo.svg",
   },
   {
     id: "https://ror.org/000h6jb29",
     favicon: "https://www.ufz.de/static/custom/weblayout/DefaultInternetLayout/img/favicon.ico",
-    logo: "https://www.wikidata.org/wiki/Q880999#/media/File:UFZ_Logo_RGB_DE.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/e/ed/UFZ_Logo_RGB_DE.png",
   },
   {
     id: "https://ror.org/01zy2cs03",
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index cca4391..e16f352 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -57,7 +57,6 @@ const ResultItem = ({
     }
 
     const iconArr = INSTITUTE_ROR_LOGOS.filter((o) => o.id === item.id).pop();
-    console.log(iconArr);
     setTitleIconHref(iconArr?.favicon || "");
     setLogoHref(iconArr?.logo || "");
   }, [item]);
@@ -134,22 +133,23 @@ const ResultItem = ({
 
   return (
     <div
-      className={`flex ${inDetailsPage && logoHref !== "" ? "" : "flex-col"}  my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 p-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto`}
+      className={`flex my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 p-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto ${inDetailsPage && logoHref !== "" ? "" : "flex-col"}`}
     >
-      <div
-        className={`${inDetailsPage && logoHref !== "" ? "border-2 border-red-400 space-y-2 p-5 mt-2 basis-1/3" : "hidden"}`}
-      >
-        <Image
-          src={logoHref}
-          className="object-contain w-20 h-20"
-          alt="Institute logo"
-          width={80}
-          height={80}
-        />
-      </div>
+      {inDetailsPage && logoHref !== "" ? (
+        <div className={`border-2 border-red-400 space-y-2 p-5 mt-2 basis-1/3`}>
+          <Image
+            src={logoHref}
+            className={`object-contain w-20 h-20`}
+            alt="Institute logo"
+            width={80}
+            height={80}
+          />
+        </div>
+      ) : null}
+
       <div
         key={idx}
-        className={`flex flex-col ${inDetailsPage && logoHref !== "" ? "basis-2/3" : ""} my-2 space-y-2 p-5 border-2 border-red-500`}
+        className={`flex flex-col my-2 space-y-2 p-5 ${inDetailsPage && logoHref !== "" ? "basis-2/3" : ""} `}
       >
         <button
           className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"} ${inDetailsPage ? "mb-5" : ""}`}
-- 
GitLab


From 299555e4f4cef8df2d38388e16032b878da78c01 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 18 Feb 2025 15:46:29 +0100
Subject: [PATCH 30/55] displaying institute icons when they exist on large
 screens

---
 next.config.mjs                               | 11 +++++-----
 src/app/api/config/config.ts                  | 20 +++++++++----------
 .../app/results/ListResults/ResultItem.tsx    | 14 ++++++-------
 3 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/next.config.mjs b/next.config.mjs
index 4b7fd1e..1740598 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -31,9 +31,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.wikidata.org",
+        hostname: "upload.wikimedia.org",
         port: "",
-        pathname: "/wiki/Q536656#/media/File:AWI_Logo_2017.svg",
+        pathname: "/wikipedia/commons/f/f7/AWI_Logo_2017.svg",
       },
       {
         protocol: "https",
@@ -86,9 +86,9 @@ const nextConfig = {
       },
       {
         protocol: "https",
-        hostname: "www.gfz-potsdam.de",
+        hostname: "www.gfz.de",
         port: "",
-        pathname: "/typo3conf/ext/gfz_www_sitepackage/Resources/Public/Icons/favicon.ico",
+        pathname: "/_assets/addb558b1d0e21da17cab6423afccec8/Icons/favicon.ico",
       },
       {
         protocol: "https",
@@ -186,7 +186,8 @@ const nextConfig = {
         protocol: "https",
         hostname: "www.dkfz.de",
         port: "",
-        pathname: "/global/img/favicon.ico",
+        pathname:
+          "/_assets/5bd5aaeffedb0553dcc3d3be99b60d08/Frontend/Images/Favicon/favicon-16x16.png",
       },
       {
         protocol: "https",
diff --git a/src/app/api/config/config.ts b/src/app/api/config/config.ts
index da4d5e3..30a16bb 100644
--- a/src/app/api/config/config.ts
+++ b/src/app/api/config/config.ts
@@ -279,7 +279,7 @@ export const INSTITUTE_ROR_LOGOS = [
   {
     id: "https://ror.org/032e6b942",
     favicon: "https://www.awi.de/_assets/978631966794c5093250775de182779d/Images/AWI/favicon.ico",
-    logo: "https://www.wikidata.org/wiki/Q536656#/media/File:AWI_Logo_2017.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/f/f7/AWI_Logo_2017.svg",
   },
   {
     id: "https://ror.org/03d0p2685",
@@ -289,8 +289,7 @@ export const INSTITUTE_ROR_LOGOS = [
   },
   {
     id: "https://ror.org/04z8jg394",
-    favicon:
-      "https://www.gfz-potsdam.de/typo3conf/ext/gfz_www_sitepackage/Resources/Public/Icons/favicon.ico",
+    favicon: "https://www.gfz.de/_assets/addb558b1d0e21da17cab6423afccec8/Icons/favicon.ico",
     logo: "https://upload.wikimedia.org/wikipedia/commons/8/86/Deutsches-GeoForschungsZentrum-Logo.svg",
   },
   {
@@ -306,17 +305,17 @@ export const INSTITUTE_ROR_LOGOS = [
   {
     id: "https://ror.org/01zy2cs03",
     favicon: "https://www.hzdr.de/favicon-16x16.png",
-    logo: "https://www.wikidata.org/wiki/Q883545#/media/File:HZDR-LOGO.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/e/e5/HZDR-LOGO.png",
   },
   {
     id: "https://ror.org/04bwf3e34",
     favicon: "https://www.dlr.de/icon.svg",
-    logo: "https://www.wikidata.org/wiki/Q157332#/media/File:DLR_Logo.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/f/f5/DLR_Logo.svg",
   },
   {
     id: "https://ror.org/02k8cbn47",
     favicon: "https://www.gsi.de/favicon.ico",
-    logo: "https://www.wikidata.org/wiki/Q703993#/media/File:GSI_Logo.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/6/6f/GSI_Logo.svg",
   },
   {
     id: "https://ror.org/00cfam450",
@@ -327,12 +326,13 @@ export const INSTITUTE_ROR_LOGOS = [
   {
     id: "https://ror.org/04t3en479",
     favicon: "https://www.kit.edu/img/intern/favicon.ico",
-    logo: "https://www.wikidata.org/wiki/Q309988#/media/File:Logo_KIT.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/3/3a/Logo_KIT.svg",
   },
   {
     id: "https://ror.org/04cdgtt98",
-    favicon: "https://www.dkfz.de/global/img/favicon.ico",
-    logo: "https://www.wikidata.org/wiki/Q449325#/media/File:Deutsches_Krebsforschungszentrum_Logo.svg",
+    favicon:
+      "https://www.dkfz.de/_assets/5bd5aaeffedb0553dcc3d3be99b60d08/Frontend/Images/Favicon/favicon-16x16.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/d/d9/Deutsches_Krebsforschungszentrum_Logo.svg",
   },
   {
     id: "https://ror.org/02njgxr09",
@@ -342,7 +342,7 @@ export const INSTITUTE_ROR_LOGOS = [
     id: "https://ror.org/043j0f473",
     favicon:
       "https://www.dzne.de/typo3conf/ext/fe_website/Resources/Public/AppIcons/favicon-16x16.png",
-    logo: "https://www.wikidata.org/wiki/Q1206136#/media/File:DZNE_Logo_CMYK.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/2/26/DZNE_Logo_CMYK.svg",
   },
   {
     id: "https://ror.org/02nv7yv05",
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index e16f352..dc194dc 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -133,23 +133,23 @@ const ResultItem = ({
 
   return (
     <div
-      className={`flex my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 p-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto ${inDetailsPage && logoHref !== "" ? "" : "flex-col"}`}
+      className={`flex my-2 space-y-2 rounded-xl border-2 border-primary-helmholtz-hellblau/20 p-5 shadow-lg shadow-secondary-helmholtz-highlightblau bg-white size-auto ${inDetailsPage && logoHref !== "" ? "xl:gap-x-10" : "xl:flex-col"}`}
     >
       {inDetailsPage && logoHref !== "" ? (
-        <div className={`border-2 border-red-400 space-y-2 p-5 mt-2 basis-1/3`}>
+        <div className="hidden xl:space-y-2 xl:p-5 xl:mt-2 xl:basis-1/3 xl:flex">
           <Image
             src={logoHref}
-            className={`object-contain w-20 h-20`}
+            className="object-contain place-self-center self-center"
             alt="Institute logo"
-            width={80}
-            height={80}
+            width={1000}
+            height={1000}
           />
         </div>
       ) : null}
 
       <div
         key={idx}
-        className={`flex flex-col my-2 space-y-2 p-5 ${inDetailsPage && logoHref !== "" ? "basis-2/3" : ""} `}
+        className={`flex flex-col my-2 space-y-2 p-5 ${inDetailsPage && logoHref !== "" ? "xl:basis-2/3" : ""} `}
       >
         <button
           className={`${inDetailsPage ? "" : "hover:transition-all hover:translate-x-3"} inline-flex align-middle items-center pb-2 text-primary-helmholtz-dunkelblau ${associatedToFilters ? "" : "inline-flex"} ${inDetailsPage ? "mb-5" : ""}`}
@@ -168,7 +168,7 @@ const ResultItem = ({
             </span>
           ) : null}
           <p
-            className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-[16px] decoration-primary-helmholtz-hellblau" : " truncate"} font-semibold text-left w-[98%] `}
+            className={`${inDetailsPage ? "inline-flex text-2xl underline underline-offset-[6px] xl:underline-offset-[8px] decoration-primary-helmholtz-hellblau" : "truncate"} font-semibold text-left w-[98%]`}
             rel="noreferrer"
           >
             {item.name}
-- 
GitLab


From eb89521a1aefbb1ec30afa643d6c973732718ac5 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 25 Feb 2025 15:09:42 +0100
Subject: [PATCH 31/55] fixes to tsconfig

---
 tsconfig.json | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tsconfig.json b/tsconfig.json
index ff836d9..1eb4d30 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -22,7 +22,8 @@
       "@/*": ["./src/*"],
       "@api/*": ["./src/app/api/*"]
     },
-    "downlevelIteration": true
+    "downlevelIteration": true,
+    "target": "ES2017"
   },
   "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
   "exclude": ["node_modules"]
-- 
GitLab


From a3a3b87628573c225de54a654185f7bfd774eb88 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 10 Mar 2025 12:35:58 +0100
Subject: [PATCH 32/55] removed the required check on established property of
 ror result item as it is not required and simplified the type

---
 package.json       |  2 +-
 src/types/types.ts | 19 ++++---------------
 yarn.lock          |  4 ++--
 3 files changed, 7 insertions(+), 18 deletions(-)

diff --git a/package.json b/package.json
index 37f7a7a..607aaf8 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
     "react": "^18",
     "react-dom": "^18",
     "react-paginate": "^8.2.0",
-    "sharp": "^0.33.4",
+    "sharp": "^0.33.5",
     "zod": "^3.22.4"
   },
   "devDependencies": {
diff --git a/src/types/types.ts b/src/types/types.ts
index fb271d2..846c537 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -93,7 +93,7 @@ export type ResultConfig = {
 
 export type ResultKeys = { keys: ResultItemKeys[] };
 
-type RorResultItemBase = {
+export type RorResultItem = {
   id: string;
   name: string;
   acronyms?: string[];
@@ -103,7 +103,7 @@ type RorResultItemBase = {
     country_code: string;
   };
   email_address?: string | null;
-  established: number;
+  established?: number;
   external_ids?: {
     FundRef?: {
       preferred: null | string;
@@ -126,28 +126,17 @@ type RorResultItemBase = {
       all: string[];
     };
   };
-  links: string[];
+  links?: string[];
   relationships?: {
     label: string;
     type: "Parent" | "Child" | "Related";
     id: string;
   }[];
-  status: string;
+  status?: string;
   types?: string[];
   wikipedia_url?: string;
 };
 
-/*
-definition of Required Utility in TS - https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype
-type Required<T> = {
-  [P in keyof T]-?: T[P]
-}
-used in to create a generic type that enforces "required" on a particular property - https://www.emmanuelgautier.com/blog/snippets/typescript-required-properties
-*/
-type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
-
-export type RorResultItem = WithRequired<RorResultItemBase, "established">;
-
 export type ResultItem = ResultDocs & ResultConfig & ResultKeys & RorResultItem;
 
 // useless for now, later if we type the entities this will help
diff --git a/yarn.lock b/yarn.lock
index 00f1331..1b44694 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6834,7 +6834,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"sharp@npm:^0.33.4":
+"sharp@npm:^0.33.5":
   version: 0.33.5
   resolution: "sharp@npm:0.33.5"
   dependencies:
@@ -7732,7 +7732,7 @@ __metadata:
     react: "npm:^18"
     react-dom: "npm:^18"
     react-paginate: "npm:^8.2.0"
-    sharp: "npm:^0.33.4"
+    sharp: "npm:^0.33.5"
     tailwindcss: "npm:^3.3.0"
     test-listen: "npm:^1.1.0"
     ts-node: "npm:^10.9.2"
-- 
GitLab


From 62afa5710b8289600f1d006f5c8b2ca031bd4299 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 10 Mar 2025 13:23:03 +0100
Subject: [PATCH 33/55] fixed a relative import

---
 src/components/app/results/Details/RelatedResults.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index d322c8c..fcd5804 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -7,7 +7,7 @@ import Error from "@/components/layout/Error";
 import Spinner from "@/components/layout/Spinner";
 import { Category } from "@/types/types";
 
-import CategoryBar from "../CategoryBar";
+import CategoryBar from "@/components/app/results/CategoryBar";
 
 const RelatedResults = () => {
   const d = useTranslations("DetailsView");
-- 
GitLab


From 51a5d7982ce0cf4644bd475e859a2865c850b904 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 10 Mar 2025 14:20:04 +0100
Subject: [PATCH 34/55] fixing issues from merge of dev into this branch

---
 src/app/[locale]/layout.tsx                    |  8 ++++++++
 src/components/app/Categories.tsx              |  3 ++-
 src/components/app/results/CategoryBar.tsx     |  3 ++-
 .../app/results/Details/RelatedResults.tsx     |  3 +--
 .../app/results/ListResults/ResultItem.tsx     |  3 ++-
 .../ListResults/ResultItem/Relationships.tsx   |  7 ++++---
 src/components/layout/Header.tsx               |  3 ++-
 src/components/layout/Search.tsx               |  3 ++-
 src/i18n/request.ts                            | 18 ++++++++++++++++++
 src/i18n/routing.ts                            | 12 ++++++++++++
 src/utils/apiCall.ts                           |  5 ++---
 11 files changed, 55 insertions(+), 13 deletions(-)
 create mode 100644 src/i18n/request.ts
 create mode 100644 src/i18n/routing.ts

diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx
index 7e924b6..d8ad8f8 100644
--- a/src/app/[locale]/layout.tsx
+++ b/src/app/[locale]/layout.tsx
@@ -1,11 +1,13 @@
 import type { Metadata, Viewport } from "next";
 import "./globals.css";
+import { notFound } from "next/navigation";
 import { useTranslations, useMessages, NextIntlClientProvider } from "next-intl";
 import React from "react";
 
 import Banner from "@/components/layout/Banner";
 import Footer from "@/components/layout/Footer";
 import Header from "@/components/layout/Header";
+import { routing } from "@/i18n/routing";
 
 const env = process.env.NEXT_PUBLIC_SHOW_BANNER;
 const showBanner = env && (env.toLowerCase() === "true" || env === "1");
@@ -42,6 +44,12 @@ export default function RootLayout({
   params: Promise<{ locale: string }>;
 }>) {
   const { locale } = React.use(params);
+
+  // Ensure that the incoming `locale` is valid
+  if (!routing.locales.includes(locale as any)) {
+    notFound();
+  }
+
   const t = useTranslations("Layout");
   const messages = useMessages();
 
diff --git a/src/components/app/Categories.tsx b/src/components/app/Categories.tsx
index 20d40bf..5554695 100644
--- a/src/components/app/Categories.tsx
+++ b/src/components/app/Categories.tsx
@@ -6,10 +6,11 @@ import { useEffect, useState } from "react";
 
 import Error from "@/components/layout/Error";
 import Spinner from "@/components/layout/Spinner";
-import { Link } from "@/i18n/routing";
 import type { Category } from "@/types/types";
 import { getAllCategories } from "@/utils/apiCall";
 
+import { Link } from "@/i18n/routing";
+
 const Categories = () => {
   const t = useTranslations("Categories");
   const [allCategories, setCategories] = useState<Category[]>([]);
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index 6bc4ffa..1d9be55 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -4,10 +4,11 @@ import { useSearchParams } from "next/navigation";
 import { useTranslations } from "next-intl";
 import { Dispatch, SetStateAction, Suspense, useEffect, useState, useRef } from "react";
 
-import { Link } from "@/i18n/routing";
 import type { Category } from "@/types/types";
 import { getAllCategories, getCategoryCounts } from "@/utils/apiCall";
 
+import { Link } from "@/i18n/routing";
+
 type Props = {
   activeCategory?: Category;
   categoryLoading: boolean;
diff --git a/src/components/app/results/Details/RelatedResults.tsx b/src/components/app/results/Details/RelatedResults.tsx
index fcd5804..451acf2 100644
--- a/src/components/app/results/Details/RelatedResults.tsx
+++ b/src/components/app/results/Details/RelatedResults.tsx
@@ -2,13 +2,12 @@
 import { useTranslations } from "next-intl";
 import React, { useState } from "react";
 
+import CategoryBar from "@/components/app/results/CategoryBar";
 import ListResults from "@/components/app/results/ListResults";
 import Error from "@/components/layout/Error";
 import Spinner from "@/components/layout/Spinner";
 import { Category } from "@/types/types";
 
-import CategoryBar from "@/components/app/results/CategoryBar";
-
 const RelatedResults = () => {
   const d = useTranslations("DetailsView");
   const [categoryLoading, setCategoryLoading] = useState(true);
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index c63b21c..e3e85e1 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -9,12 +9,13 @@ import { useEffect, useRef, useState } from "react";
 import { INSTITUTE_ROR_LOGOS } from "@/app/api/config/config";
 import ExternalLink from "@/components/ExternalLink";
 import Relationships from "@/components/app/results/ListResults/ResultItem/Relationships";
-import { Link } from "@/i18n/routing";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
 import type { Category, ResultItem as ResultItemType } from "@/types/types";
 import { detailsItemAtom } from "@/utils/atoms";
 
+import { Link } from "@/i18n/routing";
+
 type Props = {
   item: ResultItemType;
   idx: string;
diff --git a/src/components/app/results/ListResults/ResultItem/Relationships.tsx b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
index fa9762c..27d7ad1 100644
--- a/src/components/app/results/ListResults/ResultItem/Relationships.tsx
+++ b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
@@ -3,9 +3,10 @@ import { useTranslations } from "next-intl";
 import React, { useEffect, useRef, useState } from "react";
 
 import { INSTITUTE_ROR_LOGOS } from "@/app/api/config/config";
-import { Link } from "@/i18n/routing";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 
+import { Link } from "@/i18n/routing";
+
 type Props = {
   filteredArr: { label: string; type: string; id: string }[];
   type: "Parent" | "Child" | "Related";
@@ -35,7 +36,7 @@ const Relationships = ({ filteredArr, type }: Props) => {
     <div className="mt-2 cursor-default">
       <span className="font-semibold">{s(`${type.toLowerCase()}`)}: </span>
 
-      <p ref={relRef} className={relShowMore ? "" : "line-clamp-2"}>
+      <div ref={relRef} className={relShowMore ? "" : "line-clamp-2"}>
         {filteredArr.map((displayItem, idx: number) => {
           const iconArr = INSTITUTE_ROR_LOGOS.filter((o) => o.id === displayItem.id);
           const iconHref = iconArr.pop()?.favicon || "";
@@ -64,7 +65,7 @@ const Relationships = ({ filteredArr, type }: Props) => {
             </span>
           );
         })}
-      </p>
+      </div>
 
       {relShowReadMore ? (
         <button
diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx
index fc902c4..4a33106 100644
--- a/src/components/layout/Header.tsx
+++ b/src/components/layout/Header.tsx
@@ -2,10 +2,11 @@ import Image from "next/image";
 import { useTranslations } from "next-intl";
 
 import Search from "@/components/layout/Search";
-import { Link } from "@/i18n/routing";
 import logoHGF from "@/resources/images/logo/Logo_HGF-KG_text_brightback.png";
 import unhideLogo from "@/resources/images/logo/unhide_header.png";
 
+import { Link } from "@/i18n/routing";
+
 const Header = () => {
   const t = useTranslations("Search");
   const s = useTranslations("Intro");
diff --git a/src/components/layout/Search.tsx b/src/components/layout/Search.tsx
index c5f5e2f..656f8a4 100644
--- a/src/components/layout/Search.tsx
+++ b/src/components/layout/Search.tsx
@@ -3,11 +3,12 @@
 import { useSearchParams, useRouter } from "next/navigation";
 import { Suspense, useEffect, useState } from "react";
 
-import { Link } from "@/i18n/routing";
 import ClearIcon from "@/resources/images/svg/ClearIcon";
 import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
 import SearchIcon from "@/resources/images/svg/SearchIcon";
 
+import { Link } from "@/i18n/routing";
+
 type Props = {
   exampleTrigger: string;
   placeholder: string;
diff --git a/src/i18n/request.ts b/src/i18n/request.ts
new file mode 100644
index 0000000..73f0e42
--- /dev/null
+++ b/src/i18n/request.ts
@@ -0,0 +1,18 @@
+import { getRequestConfig } from "next-intl/server";
+
+import { routing } from "@/i18n/routing";
+
+export default getRequestConfig(async ({ requestLocale }) => {
+  // This typically corresponds to the `[locale]` segment
+  let locale = await requestLocale;
+
+  // Ensure that a valid locale is used
+  if (!locale || !routing.locales.includes(locale as any)) {
+    locale = routing.defaultLocale;
+  }
+
+  return {
+    locale,
+    messages: (await import(`@/locales/${locale}.json`)).default,
+  };
+});
diff --git a/src/i18n/routing.ts b/src/i18n/routing.ts
new file mode 100644
index 0000000..7d9aa72
--- /dev/null
+++ b/src/i18n/routing.ts
@@ -0,0 +1,12 @@
+import { createNavigation } from "next-intl/navigation";
+import { defineRouting, LocalePrefix } from "next-intl/routing";
+
+export const i18nConfig = {
+  locales: ["en", "de"],
+  defaultLocale: "en",
+  localeDetection: false,
+  localePrefix: "as-needed" as LocalePrefix,
+};
+export const routing = defineRouting(i18nConfig);
+
+export const { Link } = createNavigation(routing);
diff --git a/src/utils/apiCall.ts b/src/utils/apiCall.ts
index ed95087..4a6de7d 100644
--- a/src/utils/apiCall.ts
+++ b/src/utils/apiCall.ts
@@ -59,14 +59,13 @@ export async function getCategoryCounts(searchText?: string): Promise<Record<str
 }
 
 export async function getRorInfo(rorId: string): Promise<RorResultItem> {
-  const rorItem: RorResultItem = { id: "", name: "", status: "", established: 0, links: [] };
+  const rorItem: RorResultItem = { id: "", name: "", status: "" };
   const response = await fetch(`https://api.ror.org/organizations/${rorId}`, {
     headers: {
       Accept: "application/json",
     },
   });
-  const rorResult: RorResultItem = { ...rorItem, ...(await response.json()) };
-  return rorResult;
+  return { ...rorItem, ...(await response.json()) };
 }
 
 export async function search(
-- 
GitLab


From c6ac89035522e1083cdc884e1735490a614cf96d Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 10 Mar 2025 14:24:50 +0100
Subject: [PATCH 35/55] import statement corrections for i18n based Link
 component

---
 package.json                                                  | 2 +-
 src/components/app/Categories.tsx                             | 3 +--
 src/components/app/results/CategoryBar.tsx                    | 3 +--
 src/components/app/results/ListResults/ResultItem.tsx         | 3 +--
 .../app/results/ListResults/ResultItem/Relationships.tsx      | 3 +--
 src/components/layout/Header.tsx                              | 3 +--
 src/components/layout/Search.tsx                              | 3 +--
 yarn.lock                                                     | 4 ++--
 8 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/package.json b/package.json
index 4ce7040..32f8767 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
     "react": "^18",
     "react-dom": "^18",
     "react-paginate": "^8",
-    "sharp": "^0.33",
+    "sharp": "^0.33.5",
     "zod": "^3"
   },
   "devDependencies": {
diff --git a/src/components/app/Categories.tsx b/src/components/app/Categories.tsx
index 5554695..20d40bf 100644
--- a/src/components/app/Categories.tsx
+++ b/src/components/app/Categories.tsx
@@ -6,11 +6,10 @@ import { useEffect, useState } from "react";
 
 import Error from "@/components/layout/Error";
 import Spinner from "@/components/layout/Spinner";
+import { Link } from "@/i18n/routing";
 import type { Category } from "@/types/types";
 import { getAllCategories } from "@/utils/apiCall";
 
-import { Link } from "@/i18n/routing";
-
 const Categories = () => {
   const t = useTranslations("Categories");
   const [allCategories, setCategories] = useState<Category[]>([]);
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index 1d9be55..6bc4ffa 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -4,11 +4,10 @@ import { useSearchParams } from "next/navigation";
 import { useTranslations } from "next-intl";
 import { Dispatch, SetStateAction, Suspense, useEffect, useState, useRef } from "react";
 
+import { Link } from "@/i18n/routing";
 import type { Category } from "@/types/types";
 import { getAllCategories, getCategoryCounts } from "@/utils/apiCall";
 
-import { Link } from "@/i18n/routing";
-
 type Props = {
   activeCategory?: Category;
   categoryLoading: boolean;
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index e3e85e1..c63b21c 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -9,13 +9,12 @@ import { useEffect, useRef, useState } from "react";
 import { INSTITUTE_ROR_LOGOS } from "@/app/api/config/config";
 import ExternalLink from "@/components/ExternalLink";
 import Relationships from "@/components/app/results/ListResults/ResultItem/Relationships";
+import { Link } from "@/i18n/routing";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
 import type { Category, ResultItem as ResultItemType } from "@/types/types";
 import { detailsItemAtom } from "@/utils/atoms";
 
-import { Link } from "@/i18n/routing";
-
 type Props = {
   item: ResultItemType;
   idx: string;
diff --git a/src/components/app/results/ListResults/ResultItem/Relationships.tsx b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
index 27d7ad1..de00642 100644
--- a/src/components/app/results/ListResults/ResultItem/Relationships.tsx
+++ b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
@@ -3,9 +3,8 @@ import { useTranslations } from "next-intl";
 import React, { useEffect, useRef, useState } from "react";
 
 import { INSTITUTE_ROR_LOGOS } from "@/app/api/config/config";
-import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
-
 import { Link } from "@/i18n/routing";
+import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 
 type Props = {
   filteredArr: { label: string; type: string; id: string }[];
diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx
index 4a33106..fc902c4 100644
--- a/src/components/layout/Header.tsx
+++ b/src/components/layout/Header.tsx
@@ -2,11 +2,10 @@ import Image from "next/image";
 import { useTranslations } from "next-intl";
 
 import Search from "@/components/layout/Search";
+import { Link } from "@/i18n/routing";
 import logoHGF from "@/resources/images/logo/Logo_HGF-KG_text_brightback.png";
 import unhideLogo from "@/resources/images/logo/unhide_header.png";
 
-import { Link } from "@/i18n/routing";
-
 const Header = () => {
   const t = useTranslations("Search");
   const s = useTranslations("Intro");
diff --git a/src/components/layout/Search.tsx b/src/components/layout/Search.tsx
index 656f8a4..c5f5e2f 100644
--- a/src/components/layout/Search.tsx
+++ b/src/components/layout/Search.tsx
@@ -3,12 +3,11 @@
 import { useSearchParams, useRouter } from "next/navigation";
 import { Suspense, useEffect, useState } from "react";
 
+import { Link } from "@/i18n/routing";
 import ClearIcon from "@/resources/images/svg/ClearIcon";
 import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
 import SearchIcon from "@/resources/images/svg/SearchIcon";
 
-import { Link } from "@/i18n/routing";
-
 type Props = {
   exampleTrigger: string;
   placeholder: string;
diff --git a/yarn.lock b/yarn.lock
index 2feb766..41356b1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6977,7 +6977,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"sharp@npm:^0.33, sharp@npm:^0.33.5":
+"sharp@npm:^0.33.5":
   version: 0.33.5
   resolution: "sharp@npm:0.33.5"
   dependencies:
@@ -7901,7 +7901,7 @@ __metadata:
     react: "npm:^18"
     react-dom: "npm:^18"
     react-paginate: "npm:^8"
-    sharp: "npm:^0.33"
+    sharp: "npm:^0.33.5"
     tailwindcss: "npm:^3.3.0"
     test-listen: "npm:^1.1.0"
     ts-node: "npm:^10.9.2"
-- 
GitLab


From ce2cd3f9bb25da4f8d1d9faf90a205b066827ea5 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 10 Mar 2025 14:26:07 +0100
Subject: [PATCH 36/55] removed an unnecessary variable declaration

---
 .env                                       | 2 ++
 src/components/app/results/CategoryBar.tsx | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)
 create mode 100644 .env

diff --git a/.env b/.env
new file mode 100644
index 0000000..ad78553
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+NEXT_PRIVATE_SOLR_SERVICE_URL=http://localhost:8983/solr/unhide/select?
+NEXT_PUBLIC_SHOW_BANNER=false
\ No newline at end of file
diff --git a/src/components/app/results/CategoryBar.tsx b/src/components/app/results/CategoryBar.tsx
index 6bc4ffa..c58ed43 100644
--- a/src/components/app/results/CategoryBar.tsx
+++ b/src/components/app/results/CategoryBar.tsx
@@ -56,7 +56,7 @@ const CategoryBarComponent = ({
         } else {
           setBaseCategories(allCategories);
         }
-      } catch (error) {
+      } catch {
         setHasBcError(true);
       }
     };
-- 
GitLab


From c2f193a4f08d32c0ce162c2e58f9855c278efcb9 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 10 Mar 2025 14:29:07 +0100
Subject: [PATCH 37/55] removed a mistakenly sent .env file

---
 .env | 2 --
 1 file changed, 2 deletions(-)
 delete mode 100644 .env

diff --git a/.env b/.env
deleted file mode 100644
index ad78553..0000000
--- a/.env
+++ /dev/null
@@ -1,2 +0,0 @@
-NEXT_PRIVATE_SOLR_SERVICE_URL=http://localhost:8983/solr/unhide/select?
-NEXT_PUBLIC_SHOW_BANNER=false
\ No newline at end of file
-- 
GitLab


From c7952c2a9889663963e4b3fcf81d12ce84752e9a Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 18 Mar 2025 12:02:17 +0100
Subject: [PATCH 38/55] log correction in source api test cases

---
 src/app/api/__tests__/api/source.test.ts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/app/api/__tests__/api/source.test.ts b/src/app/api/__tests__/api/source.test.ts
index 053e133..eab886e 100644
--- a/src/app/api/__tests__/api/source.test.ts
+++ b/src/app/api/__tests__/api/source.test.ts
@@ -7,7 +7,7 @@ import documentSource from "@api/__tests__/expectedApiResults/12.documentSource.
 import datasetSource from "@api/__tests__/expectedApiResults/13.datasetSource.json";
 import { GET } from "@api/source/route";
 
-describe("unit tests for /categories API Endpoint", () => {
+describe("unit tests for /source API Endpoint", () => {
   afterEach(() => {
     jest.resetAllMocks();
   });
@@ -39,7 +39,7 @@ describe("unit tests for /categories API Endpoint", () => {
     });
   });
 
-  it("should return json source for given document ID", async () => {
+  it("12. should return json source for given document ID", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
         json: () => Promise.resolve(solrdocumentResponse),
@@ -55,7 +55,7 @@ describe("unit tests for /categories API Endpoint", () => {
     expect(jsonResult).toMatchObject(documentSource);
   });
 
-  it("should return json source for given dataset ID", async () => {
+  it("13. should return json source for given dataset ID", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
         json: () => Promise.resolve(solrDatasetResponse),
-- 
GitLab


From 618c1e74b99dc02617db04125e4961a1e25a6ac6 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 18 Mar 2025 13:21:33 +0100
Subject: [PATCH 39/55] initial draft of tests for details api

---
 src/app/api/__tests__/api/details.test.ts | 182 ++++++++++++++++++++++
 1 file changed, 182 insertions(+)
 create mode 100644 src/app/api/__tests__/api/details.test.ts

diff --git a/src/app/api/__tests__/api/details.test.ts b/src/app/api/__tests__/api/details.test.ts
new file mode 100644
index 0000000..ff3d20a
--- /dev/null
+++ b/src/app/api/__tests__/api/details.test.ts
@@ -0,0 +1,182 @@
+import { NextRequest } from "next/server";
+
+import solrdocumentResponse from "@api/__tests__/__mocks__/solrResults/12.documentSource.json";
+import solrDatasetResponse from "@api/__tests__/__mocks__/solrResults/13.datasetSource.json";
+import solrWrongIdResponse from "@api/__tests__/__mocks__/solrResults/14.wrongIdSource.json";
+import documentSource from "@api/__tests__/expectedApiResults/12.documentSource.json";
+import datasetSource from "@api/__tests__/expectedApiResults/13.datasetSource.json";
+import { GET } from "@api/source/route";
+
+describe("unit tests for /details API Endpoint", () => {
+  afterEach(() => {
+    jest.resetAllMocks();
+  });
+
+  it("should return an error when no ID is passed as a param", async () => {
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("documentType", "document");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(400);
+    expect(jsonResult).toMatchObject({
+      error: {
+        message: "Request missing ID parameter",
+      },
+    });
+  });
+
+  it("should return an error when no documentType is passed as a param", async () => {
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(400);
+    expect(jsonResult).toMatchObject({
+      error: {
+        message: "Request missing documentType parameter",
+      },
+    });
+  });
+
+  it("should return an error when both ID and documentType are not passed as a param", async () => {
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(400);
+    expect(jsonResult).toMatchObject({
+      error: {
+        message: "Request missing ID or documentType parameter",
+      },
+    });
+  });
+
+  it("should return an error on being given an id and misformed documentType", async () => {
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
+    req.nextUrl.searchParams.append("documentType", "documen");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(400);
+    expect(jsonResult).toMatchObject({
+      error: {
+        message: "No results found for given ID and documentType",
+      },
+    });
+  });
+
+  it("should return an error on being given an empty string for id", async () => {
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "");
+    req.nextUrl.searchParams.append("documentType", "document");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(400);
+    expect(jsonResult).toMatchObject({
+      error: {
+        message: "Request missing ID parameter",
+      },
+    });
+  });
+
+  it("15.should return an error on being given an misformed id and correct documentType", async () => {
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "1234567890");
+    req.nextUrl.searchParams.append("documentType", "document");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(400);
+    expect(jsonResult).toMatchObject({
+      error: {
+        message: "No results found for given ID and documentType",
+      },
+    });
+  });
+
+  it("16.should return an error on being given an correct id and incorrect documentType", async () => {
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
+    req.nextUrl.searchParams.append("documentType", "document");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(400);
+    expect(jsonResult).toMatchObject({
+      error: {
+        message: "No results found for given ID and documentType",
+      },
+    });
+  });
+
+  it("17.should return result item for given documentType and ID", async () => {
+    jest.spyOn(global, "fetch").mockImplementationOnce(() =>
+      Promise.resolve({
+        json: () => Promise.resolve(solrdocumentResponse),
+      } as Response)
+    );
+
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "https://doi.org/10.5281/zenodo.14945361");
+    req.nextUrl.searchParams.append("documentType", "software");
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(200);
+    expect(jsonResult).toMatchObject(documentSource);
+  });
+
+  it("18.should return result item for the institute with given ID, without any ROR enrichment", async () => {
+    jest.spyOn(global, "fetch").mockImplementationOnce(() =>
+      Promise.resolve({
+        json: () => Promise.resolve(solrDatasetResponse),
+      } as Response)
+    );
+
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "https://doi.org/10.13039/100009133");
+    req.nextUrl.searchParams.append("documentType", "institutions");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(200);
+    expect(jsonResult).toMatchObject(datasetSource);
+  });
+
+  it("19.should return result item for the institute with given ID,with ROR enrichment but without any information about logos", async () => {
+    jest.spyOn(global, "fetch").mockImplementationOnce(() =>
+      Promise.resolve({
+        json: () => Promise.resolve(solrDatasetResponse),
+      } as Response)
+    );
+
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "https://ror.org/04aj4c181");
+    req.nextUrl.searchParams.append("documentType", "institutions");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(200);
+    expect(jsonResult).toMatchObject(datasetSource);
+  });
+
+  it("20.should return result item for the institute with given ID,with ROR enrichment but with information on logos", async () => {
+    jest.spyOn(global, "fetch").mockImplementationOnce(() =>
+      Promise.resolve({
+        json: () => Promise.resolve(solrDatasetResponse),
+      } as Response)
+    );
+
+    const req = new NextRequest(new Request("https://www.whatever.com"), {});
+    req.nextUrl.searchParams.append("id", "https://ror.org/0281dp749");
+    req.nextUrl.searchParams.append("documentType", "institutions");
+
+    const response = await GET(req);
+    const jsonResult = await response.json();
+    expect(response.status).toBe(200);
+    expect(jsonResult).toMatchObject(datasetSource);
+  });
+});
-- 
GitLab


From a3e2b64b929b2f642235fa76e1530f1b8df74a36 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 18 Mar 2025 16:07:54 +0100
Subject: [PATCH 40/55] added basic error response files and got the first
 three test cases running

---
 src/app/api/__tests__/api/details.test.ts     | 68 ++++++--------
 .../expectedApiResults/15.missingId.json      | 14 +++
 .../16.missingDocumentType.json               | 14 +++
 .../expectedApiResults/17.missingParams.json  | 21 +++++
 .../expectedApiResults/18.invalidDocType.json | 16 ++++
 .../expectedApiResults/19.emptyStringId.json  | 16 ++++
 src/app/api/details/route.ts                  | 93 +++++++++++++++++++
 src/types/types.ts                            | 16 ++++
 8 files changed, 216 insertions(+), 42 deletions(-)
 create mode 100644 src/app/api/__tests__/expectedApiResults/15.missingId.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/16.missingDocumentType.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/17.missingParams.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/19.emptyStringId.json
 create mode 100644 src/app/api/details/route.ts

diff --git a/src/app/api/__tests__/api/details.test.ts b/src/app/api/__tests__/api/details.test.ts
index ff3d20a..3e8ea46 100644
--- a/src/app/api/__tests__/api/details.test.ts
+++ b/src/app/api/__tests__/api/details.test.ts
@@ -2,58 +2,50 @@ import { NextRequest } from "next/server";
 
 import solrdocumentResponse from "@api/__tests__/__mocks__/solrResults/12.documentSource.json";
 import solrDatasetResponse from "@api/__tests__/__mocks__/solrResults/13.datasetSource.json";
-import solrWrongIdResponse from "@api/__tests__/__mocks__/solrResults/14.wrongIdSource.json";
 import documentSource from "@api/__tests__/expectedApiResults/12.documentSource.json";
 import datasetSource from "@api/__tests__/expectedApiResults/13.datasetSource.json";
-import { GET } from "@api/source/route";
+import missingId from "@api/__tests__/expectedApiResults/15.missingId.json";
+import missingDocumentType from "@api/__tests__/expectedApiResults/16.missingDocumentType.json";
+import missingParams from "@api/__tests__/expectedApiResults/17.missingParams.json";
+import invalidDocType from "@api/__tests__/expectedApiResults/18.invalidDocType.json";
+import emptyStringId from "@api/__tests__/expectedApiResults/19.emptyStringId.json";
+import { GET } from "@api/details/route";
 
 describe("unit tests for /details API Endpoint", () => {
   afterEach(() => {
     jest.resetAllMocks();
   });
 
-  it("should return an error when no ID is passed as a param", async () => {
+  it("15. should return an error when no ID is passed as a param", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
-    req.nextUrl.searchParams.append("documentType", "document");
+    req.nextUrl.searchParams.append("documentType", "documents");
 
     const response = await GET(req);
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
-    expect(jsonResult).toMatchObject({
-      error: {
-        message: "Request missing ID parameter",
-      },
-    });
+    expect(jsonResult).toMatchObject(missingId);
   });
 
-  it("should return an error when no documentType is passed as a param", async () => {
+  it("16. should return an error when no documentType is passed as a param", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
 
     const response = await GET(req);
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
-    expect(jsonResult).toMatchObject({
-      error: {
-        message: "Request missing documentType parameter",
-      },
-    });
+    expect(jsonResult).toMatchObject(missingDocumentType);
   });
 
-  it("should return an error when both ID and documentType are not passed as a param", async () => {
+  it("17.should return an error when both ID and documentType are not passed as a param", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
 
     const response = await GET(req);
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
-    expect(jsonResult).toMatchObject({
-      error: {
-        message: "Request missing ID or documentType parameter",
-      },
-    });
+    expect(jsonResult).toMatchObject(missingParams);
   });
 
-  it("should return an error on being given an id and misformed documentType", async () => {
+  it.skip("18. should return an error on being given an id and invalid documentType", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
     req.nextUrl.searchParams.append("documentType", "documen");
@@ -61,32 +53,24 @@ describe("unit tests for /details API Endpoint", () => {
     const response = await GET(req);
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
-    expect(jsonResult).toMatchObject({
-      error: {
-        message: "No results found for given ID and documentType",
-      },
-    });
+    expect(jsonResult).toMatchObject(invalidDocType);
   });
 
-  it("should return an error on being given an empty string for id", async () => {
+  it.skip("19. should return an error on being given an empty string for id", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "");
-    req.nextUrl.searchParams.append("documentType", "document");
+    req.nextUrl.searchParams.append("documentType", "documents");
 
     const response = await GET(req);
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
-    expect(jsonResult).toMatchObject({
-      error: {
-        message: "Request missing ID parameter",
-      },
-    });
+    expect(jsonResult).toMatchObject(emptyStringId);
   });
 
-  it("15.should return an error on being given an misformed id and correct documentType", async () => {
+  it.skip("20.should return an error on being given an misformed id and correct documentType", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "1234567890");
-    req.nextUrl.searchParams.append("documentType", "document");
+    req.nextUrl.searchParams.append("documentType", "documents");
 
     const response = await GET(req);
     const jsonResult = await response.json();
@@ -98,10 +82,10 @@ describe("unit tests for /details API Endpoint", () => {
     });
   });
 
-  it("16.should return an error on being given an correct id and incorrect documentType", async () => {
+  it.skip("21.should return an error on being given an correct id and incorrect documentType", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
-    req.nextUrl.searchParams.append("documentType", "document");
+    req.nextUrl.searchParams.append("documentType", "documents");
 
     const response = await GET(req);
     const jsonResult = await response.json();
@@ -113,7 +97,7 @@ describe("unit tests for /details API Endpoint", () => {
     });
   });
 
-  it("17.should return result item for given documentType and ID", async () => {
+  it.skip("22.should return result item for given documentType and ID", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
         json: () => Promise.resolve(solrdocumentResponse),
@@ -129,7 +113,7 @@ describe("unit tests for /details API Endpoint", () => {
     expect(jsonResult).toMatchObject(documentSource);
   });
 
-  it("18.should return result item for the institute with given ID, without any ROR enrichment", async () => {
+  it.skip("23.should return result item for the institute with given ID, without any ROR enrichment", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
         json: () => Promise.resolve(solrDatasetResponse),
@@ -146,7 +130,7 @@ describe("unit tests for /details API Endpoint", () => {
     expect(jsonResult).toMatchObject(datasetSource);
   });
 
-  it("19.should return result item for the institute with given ID,with ROR enrichment but without any information about logos", async () => {
+  it.skip("24.should return result item for the institute with given ID,with ROR enrichment but without any information about logos", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
         json: () => Promise.resolve(solrDatasetResponse),
@@ -163,7 +147,7 @@ describe("unit tests for /details API Endpoint", () => {
     expect(jsonResult).toMatchObject(datasetSource);
   });
 
-  it("20.should return result item for the institute with given ID,with ROR enrichment but with information on logos", async () => {
+  it.skip("25.should return result item for the institute with given ID,with ROR enrichment but with information on logos", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
         json: () => Promise.resolve(solrDatasetResponse),
diff --git a/src/app/api/__tests__/expectedApiResults/15.missingId.json b/src/app/api/__tests__/expectedApiResults/15.missingId.json
new file mode 100644
index 0000000..f4b8dd0
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/15.missingId.json
@@ -0,0 +1,14 @@
+{
+  "error": {
+    "message": "Request missing id parameter",
+    "errors": [
+      {
+        "code": "invalid_type",
+        "expected": "string",
+        "message": "Required",
+        "path": ["id"],
+        "received": "undefined"
+      }
+    ]
+  }
+}
diff --git a/src/app/api/__tests__/expectedApiResults/16.missingDocumentType.json b/src/app/api/__tests__/expectedApiResults/16.missingDocumentType.json
new file mode 100644
index 0000000..5b46f67
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/16.missingDocumentType.json
@@ -0,0 +1,14 @@
+{
+  "error": {
+    "message": "Request missing documentType parameter",
+    "errors": [
+      {
+        "code": "invalid_type",
+        "expected": "string",
+        "received": "undefined",
+        "path": ["documentType"],
+        "message": "Required"
+      }
+    ]
+  }
+}
diff --git a/src/app/api/__tests__/expectedApiResults/17.missingParams.json b/src/app/api/__tests__/expectedApiResults/17.missingParams.json
new file mode 100644
index 0000000..a017a6e
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/17.missingParams.json
@@ -0,0 +1,21 @@
+{
+  "error": {
+    "message": "Request missing id and documentType parameters",
+    "errors": [
+      {
+        "code": "invalid_type",
+        "expected": "string",
+        "received": "undefined",
+        "path": ["id"],
+        "message": "Required"
+      },
+      {
+        "code": "invalid_type",
+        "expected": "string",
+        "received": "undefined",
+        "path": ["documentType"],
+        "message": "Required"
+      }
+    ]
+  }
+}
diff --git a/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json b/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
new file mode 100644
index 0000000..3c25aa2
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
@@ -0,0 +1,16 @@
+{
+  "error": {
+    "message": "Invalid request",
+    "errors": [
+      {
+        "code": "too_big",
+        "maximum": 10,
+        "type": "number",
+        "inclusive": true,
+        "exact": false,
+        "message": "Number must be less than or equal to 10",
+        "path": ["rows"]
+      }
+    ]
+  }
+}
diff --git a/src/app/api/__tests__/expectedApiResults/19.emptyStringId.json b/src/app/api/__tests__/expectedApiResults/19.emptyStringId.json
new file mode 100644
index 0000000..3c25aa2
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/19.emptyStringId.json
@@ -0,0 +1,16 @@
+{
+  "error": {
+    "message": "Invalid request",
+    "errors": [
+      {
+        "code": "too_big",
+        "maximum": 10,
+        "type": "number",
+        "inclusive": true,
+        "exact": false,
+        "message": "Number must be less than or equal to 10",
+        "path": ["rows"]
+      }
+    ]
+  }
+}
diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
new file mode 100644
index 0000000..fd6208f
--- /dev/null
+++ b/src/app/api/details/route.ts
@@ -0,0 +1,93 @@
+import { type NextRequest } from "next/server";
+
+import { detailsSchema } from "@/types/types";
+import { createSearchParamsMap } from "@api/utils/shared";
+
+export const GET = async (req: NextRequest) => {
+  try {
+    const detailsParamsMap = createSearchParamsMap(req.nextUrl.searchParams);
+
+    const requestBody = detailsSchema.safeParse(Object.fromEntries(detailsParamsMap));
+    if (!requestBody.success) {
+      const { errors } = requestBody.error;
+      if (errors.length === 1 && errors[0].code === "invalid_type") {
+        if (errors[0].message === "Required") {
+          return Response.json(
+            { error: { message: `Request missing ${errors[0].path[0]} parameter`, errors } },
+            { status: 400 }
+          );
+        }
+      } else if (
+        errors.length === 2 &&
+        errors[0].code === "invalid_type" &&
+        errors[1].code === "invalid_type"
+      ) {
+        console.log("errors", errors);
+        return Response.json(
+          {
+            error: {
+              message: `Request missing ${errors[0].path[0]} and ${errors[1].path[0]} parameters`,
+              errors,
+            },
+          },
+          { status: 400 }
+        );
+      }
+    }
+
+    // const {
+    //   searchText,
+    //   start,
+    //   rows,
+    //   facetType,
+    //   facetName,
+    //   documentType,
+    //   region,
+    //   includeFacets,
+    // }: searchParamsType = requestBody.data;
+
+    // // build SOLR query, query the SOLR instance for data
+    // const { facetIntervalFields, queryFacetFields } = createFacetParams(documentType);
+    // const solrResponse: SolrResponseType = await new SolrQuery(
+    //   start,
+    //   rows,
+    //   queryFacetFields,
+    //   facetIntervalFields,
+    //   facetType,
+    //   facetName,
+    //   searchText,
+    //   documentType,
+    //   region
+    // ).json();
+
+    // // create the response object in the desired shape
+    // const responseRecords: ResultItem[] = solrResponse.response.docs.map(
+    //   (record: SolrResponseDocsType) => createResultItem(record)
+    // );
+
+    // const responseTotalCount = solrResponse.response.numFound;
+
+    // const categoryCounts = updateCategoryCountsForSearch(
+    //   getSolrCategoryCountsMap(solrResponse.facet_counts.facet_fields.type)
+    // );
+
+    // const responseFilters = includeFacets
+    //   ? createResultFilters(solrResponse.facet_counts.facet_fields)
+    //   : [];
+
+    // const response: SearchResponse = {
+    //   records: responseRecords,
+    //   totalCount: responseTotalCount,
+    //   categoryCounts,
+    //   filters: responseFilters,
+    // };
+
+    // return Response.json(response);
+  } catch (error) {
+    console.error("Error while handling details", error);
+    return Response.json(
+      { error: { message: "Error while fetching details data" } },
+      { status: 500 }
+    );
+  }
+};
diff --git a/src/types/types.ts b/src/types/types.ts
index 846c537..25adae1 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -198,3 +198,19 @@ export const searchSchema = z.object({
 });
 
 export type searchParamsType = z.infer<typeof searchSchema>;
+
+export const detailsSchema = z.object({
+  id: z.string(),
+  documentType: z.union([
+    z.literal("experts"),
+    z.literal("institutions"),
+    z.literal("datasets"),
+    z.literal("documents"),
+    z.literal("trainings"),
+    z.literal("projects"),
+    z.literal("software"),
+    z.literal("instruments"),
+  ]),
+});
+
+export type detailsParamsType = z.infer<typeof detailsSchema>;
-- 
GitLab


From 21f8f1ee80b64bb3ccdc473e7550fedd99b5c9e0 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 19 Mar 2025 10:26:40 +0100
Subject: [PATCH 41/55] handled two more test cases to handle invalid params
 for details api and created a separate function to handle different error
 cases

---
 src/app/api/__tests__/api/details.test.ts     |  8 ++---
 .../expectedApiResults/18.invalidDocType.json | 12 +++----
 .../expectedApiResults/19.emptyStringId.json  | 12 +++----
 src/app/api/details/route.ts                  | 28 ++---------------
 src/app/api/utils/shared.ts                   | 23 ++++++++++++++
 src/types/types.ts                            | 31 ++++++++++++-------
 6 files changed, 58 insertions(+), 56 deletions(-)

diff --git a/src/app/api/__tests__/api/details.test.ts b/src/app/api/__tests__/api/details.test.ts
index 3e8ea46..5092615 100644
--- a/src/app/api/__tests__/api/details.test.ts
+++ b/src/app/api/__tests__/api/details.test.ts
@@ -16,7 +16,7 @@ describe("unit tests for /details API Endpoint", () => {
     jest.resetAllMocks();
   });
 
-  it("15. should return an error when no ID is passed as a param", async () => {
+  it("15.should return an error when no ID is passed as a param", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("documentType", "documents");
 
@@ -26,7 +26,7 @@ describe("unit tests for /details API Endpoint", () => {
     expect(jsonResult).toMatchObject(missingId);
   });
 
-  it("16. should return an error when no documentType is passed as a param", async () => {
+  it("16.should return an error when no documentType is passed as a param", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
 
@@ -45,7 +45,7 @@ describe("unit tests for /details API Endpoint", () => {
     expect(jsonResult).toMatchObject(missingParams);
   });
 
-  it.skip("18. should return an error on being given an id and invalid documentType", async () => {
+  it("18.should return an error on being given an id and invalid documentType", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
     req.nextUrl.searchParams.append("documentType", "documen");
@@ -56,7 +56,7 @@ describe("unit tests for /details API Endpoint", () => {
     expect(jsonResult).toMatchObject(invalidDocType);
   });
 
-  it.skip("19. should return an error on being given an empty string for id", async () => {
+  it("19.should return an error on being given an empty string for id", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "");
     req.nextUrl.searchParams.append("documentType", "documents");
diff --git a/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json b/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
index 3c25aa2..a7b4290 100644
--- a/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
+++ b/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
@@ -1,15 +1,11 @@
 {
   "error": {
-    "message": "Invalid request",
+    "message": "Document type submitted is invalid",
     "errors": [
       {
-        "code": "too_big",
-        "maximum": 10,
-        "type": "number",
-        "inclusive": true,
-        "exact": false,
-        "message": "Number must be less than or equal to 10",
-        "path": ["rows"]
+        "code": "custom",
+        "message": "Invalid document type",
+        "path": ["documentType"]
       }
     ]
   }
diff --git a/src/app/api/__tests__/expectedApiResults/19.emptyStringId.json b/src/app/api/__tests__/expectedApiResults/19.emptyStringId.json
index 3c25aa2..74d4d0e 100644
--- a/src/app/api/__tests__/expectedApiResults/19.emptyStringId.json
+++ b/src/app/api/__tests__/expectedApiResults/19.emptyStringId.json
@@ -1,15 +1,11 @@
 {
   "error": {
-    "message": "Invalid request",
+    "message": "ID cannot be an empty string",
     "errors": [
       {
-        "code": "too_big",
-        "maximum": 10,
-        "type": "number",
-        "inclusive": true,
-        "exact": false,
-        "message": "Number must be less than or equal to 10",
-        "path": ["rows"]
+        "code": "custom",
+        "message": "ID cannot be an empty string",
+        "path": ["id"]
       }
     ]
   }
diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index fd6208f..ac3a746 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -1,38 +1,16 @@
 import { type NextRequest } from "next/server";
 
 import { detailsSchema } from "@/types/types";
-import { createSearchParamsMap } from "@api/utils/shared";
+import { createSearchParamsMap, handleDetailsParamErrors } from "@api/utils/shared";
 
 export const GET = async (req: NextRequest) => {
   try {
     const detailsParamsMap = createSearchParamsMap(req.nextUrl.searchParams);
-
     const requestBody = detailsSchema.safeParse(Object.fromEntries(detailsParamsMap));
+
     if (!requestBody.success) {
       const { errors } = requestBody.error;
-      if (errors.length === 1 && errors[0].code === "invalid_type") {
-        if (errors[0].message === "Required") {
-          return Response.json(
-            { error: { message: `Request missing ${errors[0].path[0]} parameter`, errors } },
-            { status: 400 }
-          );
-        }
-      } else if (
-        errors.length === 2 &&
-        errors[0].code === "invalid_type" &&
-        errors[1].code === "invalid_type"
-      ) {
-        console.log("errors", errors);
-        return Response.json(
-          {
-            error: {
-              message: `Request missing ${errors[0].path[0]} and ${errors[1].path[0]} parameters`,
-              errors,
-            },
-          },
-          { status: 400 }
-        );
-      }
+      return handleDetailsParamErrors(errors);
     }
 
     // const {
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index ef7d200..ea96f99 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -23,6 +23,7 @@ import {
   type ResultConfig,
   type ResultKeys,
 } from "@/types/types";
+import { ZodError, ZodIssue } from "zod";
 
 export function createSearchParamsMap(nextParams: URLSearchParams) {
   const searchParams = new Map();
@@ -172,3 +173,25 @@ export const createResultFilters = (
       }));
     })
     .reduce((acc, curr) => acc?.concat(curr), []);
+
+export const handleDetailsParamErrors = (errors: ZodIssue[]) => {
+  const errorResponse = (message: string) =>
+    Response.json({ error: { message, errors } }, { status: 400 });
+
+  if (errors.every((error) => error.code === "invalid_type" && error.message === "Required")) {
+    const missingParams = errors.map((e) => e.path[0]).join(" and ");
+    return errorResponse(
+      `Request missing ${missingParams} parameter${errors.length > 1 ? "s" : ""}`
+    );
+  }
+
+  const firstError = errors[0];
+  if (firstError.code === "custom") {
+    if (firstError.message === "Invalid document type") {
+      return errorResponse("Document type submitted is invalid");
+    }
+    if (firstError.message === "ID cannot be an empty string") {
+      return errorResponse("ID cannot be an empty string");
+    }
+  }
+};
diff --git a/src/types/types.ts b/src/types/types.ts
index 25adae1..31a2493 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -200,17 +200,26 @@ export const searchSchema = z.object({
 export type searchParamsType = z.infer<typeof searchSchema>;
 
 export const detailsSchema = z.object({
-  id: z.string(),
-  documentType: z.union([
-    z.literal("experts"),
-    z.literal("institutions"),
-    z.literal("datasets"),
-    z.literal("documents"),
-    z.literal("trainings"),
-    z.literal("projects"),
-    z.literal("software"),
-    z.literal("instruments"),
-  ]),
+  id: z.string().refine((val) => val !== "", {
+    message: "ID cannot be an empty string",
+  }),
+  documentType: z.string().refine(
+    (val) => {
+      return [
+        "experts",
+        "institutions",
+        "datasets",
+        "documents",
+        "trainings",
+        "projects",
+        "software",
+        "instruments",
+      ].includes(val);
+    },
+    {
+      message: "Invalid document type",
+    }
+  ),
 });
 
 export type detailsParamsType = z.infer<typeof detailsSchema>;
-- 
GitLab


From 5dd219be378f48669bb42aa94f9b64b506830048 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 19 Mar 2025 11:44:35 +0100
Subject: [PATCH 42/55] updated error handling for details api params to handle
 correct type for documentType

---
 .eslintrc.json                                | 17 +++-
 .../16.missingDocumentType.json               | 90 +++++++++++++++++--
 .../expectedApiResults/17.missingParams.json  | 88 +++++++++++++++++-
 .../expectedApiResults/18.invalidDocType.json | 88 +++++++++++++++++-
 src/app/api/details/route.ts                  | 49 +++++-----
 src/app/api/utils/shared.ts                   | 38 +++++---
 src/types/types.ts                            | 27 +++---
 7 files changed, 328 insertions(+), 69 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index 8165096..918a7be 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -25,5 +25,20 @@
     "default-case-last": "error",
     "max-lines-per-function": ["error", 500],
     "react/no-is-mounted": "off" //debug the linting issue when this is on
-  }
+  },
+  "overrides": [
+    {
+      "files": ["src/app/api/**/*.{js,ts}"],
+      "rules": {
+        "camelcase": "off"
+      }
+    }
+    // {
+    //   "files": ["src/app/**/*.{js,ts,jsx,tsx}"],
+    //   "excludedFiles": ["src/app/api/**/*.{js,ts}"],
+    //   "rules": {
+    //     "no-console": "error"
+    //   }
+    // }
+  ]
 }
diff --git a/src/app/api/__tests__/expectedApiResults/16.missingDocumentType.json b/src/app/api/__tests__/expectedApiResults/16.missingDocumentType.json
index 5b46f67..fd8a744 100644
--- a/src/app/api/__tests__/expectedApiResults/16.missingDocumentType.json
+++ b/src/app/api/__tests__/expectedApiResults/16.missingDocumentType.json
@@ -1,13 +1,93 @@
 {
   "error": {
-    "message": "Request missing documentType parameter",
+    "message": "Document type submitted is invalid",
     "errors": [
       {
-        "code": "invalid_type",
-        "expected": "string",
-        "received": "undefined",
+        "code": "invalid_union",
+        "unionErrors": [
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "experts",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"experts\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "institutions",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"institutions\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "datasets",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"datasets\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "documents",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"documents\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "trainings",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"trainings\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "projects",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"projects\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "software",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"software\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "instruments",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"instruments\""
+              }
+            ]
+          }
+        ],
         "path": ["documentType"],
-        "message": "Required"
+        "message": "Invalid input"
       }
     ]
   }
diff --git a/src/app/api/__tests__/expectedApiResults/17.missingParams.json b/src/app/api/__tests__/expectedApiResults/17.missingParams.json
index a017a6e..6854934 100644
--- a/src/app/api/__tests__/expectedApiResults/17.missingParams.json
+++ b/src/app/api/__tests__/expectedApiResults/17.missingParams.json
@@ -10,11 +10,91 @@
         "message": "Required"
       },
       {
-        "code": "invalid_type",
-        "expected": "string",
-        "received": "undefined",
+        "code": "invalid_union",
+        "unionErrors": [
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "experts",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"experts\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "institutions",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"institutions\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "datasets",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"datasets\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "documents",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"documents\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "trainings",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"trainings\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "projects",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"projects\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "software",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"software\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "instruments",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"instruments\""
+              }
+            ]
+          }
+        ],
         "path": ["documentType"],
-        "message": "Required"
+        "message": "Invalid input"
       }
     ]
   }
diff --git a/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json b/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
index a7b4290..fd8a744 100644
--- a/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
+++ b/src/app/api/__tests__/expectedApiResults/18.invalidDocType.json
@@ -3,9 +3,91 @@
     "message": "Document type submitted is invalid",
     "errors": [
       {
-        "code": "custom",
-        "message": "Invalid document type",
-        "path": ["documentType"]
+        "code": "invalid_union",
+        "unionErrors": [
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "experts",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"experts\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "institutions",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"institutions\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "datasets",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"datasets\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "documents",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"documents\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "trainings",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"trainings\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "projects",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"projects\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "software",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"software\""
+              }
+            ]
+          },
+          {
+            "issues": [
+              {
+                "code": "invalid_literal",
+                "expected": "instruments",
+                "path": ["documentType"],
+                "message": "Invalid literal value, expected \"instruments\""
+              }
+            ]
+          }
+        ],
+        "path": ["documentType"],
+        "message": "Invalid input"
       }
     ]
   }
diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index ac3a746..693cc4c 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -1,7 +1,14 @@
 import { type NextRequest } from "next/server";
 
-import { detailsSchema } from "@/types/types";
-import { createSearchParamsMap, handleDetailsParamErrors } from "@api/utils/shared";
+import { detailsParamsType, detailsSchema, SolrResponseType } from "@/types/types";
+import { SOLR_QUERY_DEFAULTS } from "@api/config/config";
+import {
+  createFacetParams,
+  createSearchParamsMap,
+  handleDetailsParamErrors,
+} from "@api/utils/shared";
+
+import SolrQuery from "../utils/solrQuery";
 
 export const GET = async (req: NextRequest) => {
   try {
@@ -13,30 +20,22 @@ export const GET = async (req: NextRequest) => {
       return handleDetailsParamErrors(errors);
     }
 
-    // const {
-    //   searchText,
-    //   start,
-    //   rows,
-    //   facetType,
-    //   facetName,
-    //   documentType,
-    //   region,
-    //   includeFacets,
-    // }: searchParamsType = requestBody.data;
+    const { id, documentType }: detailsParamsType = requestBody.data;
+    const searchText = `id:${id}`;
+    // build SOLR query, query the SOLR instance for data
+    const { facetIntervalFields, queryFacetFields } = createFacetParams(documentType);
+    const solrResponse: SolrResponseType = await new SolrQuery(
+      SOLR_QUERY_DEFAULTS.start,
+      SOLR_QUERY_DEFAULTS.rows,
+      queryFacetFields,
+      facetIntervalFields,
+      undefined,
+      undefined,
+      searchText,
+      documentType
+    ).json();
 
-    // // build SOLR query, query the SOLR instance for data
-    // const { facetIntervalFields, queryFacetFields } = createFacetParams(documentType);
-    // const solrResponse: SolrResponseType = await new SolrQuery(
-    //   start,
-    //   rows,
-    //   queryFacetFields,
-    //   facetIntervalFields,
-    //   facetType,
-    //   facetName,
-    //   searchText,
-    //   documentType,
-    //   region
-    // ).json();
+    console.log("solrResponse", solrResponse);
 
     // // create the response object in the desired shape
     // const responseRecords: ResultItem[] = solrResponse.response.docs.map(
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index ea96f99..5ace810 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -1,3 +1,5 @@
+import { ZodIssue } from "zod";
+
 import {
   AVAILABLE_FACETS,
   FACET_FIELDS,
@@ -23,7 +25,6 @@ import {
   type ResultConfig,
   type ResultKeys,
 } from "@/types/types";
-import { ZodError, ZodIssue } from "zod";
 
 export function createSearchParamsMap(nextParams: URLSearchParams) {
   const searchParams = new Map();
@@ -178,20 +179,29 @@ export const handleDetailsParamErrors = (errors: ZodIssue[]) => {
   const errorResponse = (message: string) =>
     Response.json({ error: { message, errors } }, { status: 400 });
 
-  if (errors.every((error) => error.code === "invalid_type" && error.message === "Required")) {
-    const missingParams = errors.map((e) => e.path[0]).join(" and ");
-    return errorResponse(
-      `Request missing ${missingParams} parameter${errors.length > 1 ? "s" : ""}`
-    );
+  if (errors.length === 1) {
+    const { code, message } = errors[0];
+
+    const errorMessages = {
+      custom: message === "ID cannot be an empty string" && message,
+      invalid_union: message === "Invalid input" && "Document type submitted is invalid",
+      invalid_type: message === "Required" && "Request missing id parameter",
+    };
+
+    const errorMessage = errorMessages[code as keyof typeof errorMessages];
+    if (errorMessage) return errorResponse(errorMessage);
   }
 
-  const firstError = errors[0];
-  if (firstError.code === "custom") {
-    if (firstError.message === "Invalid document type") {
-      return errorResponse("Document type submitted is invalid");
-    }
-    if (firstError.message === "ID cannot be an empty string") {
-      return errorResponse("ID cannot be an empty string");
-    }
+  const isMultiParamError =
+    errors.length > 1 &&
+    errors.every(
+      (error) =>
+        (error.code === "invalid_type" && error.message === "Required") ||
+        (error.code === "invalid_union" && error.message === "Invalid input")
+    );
+
+  if (isMultiParamError) {
+    const missingParams = errors.map((e) => e.path[0]).join(" and ");
+    return errorResponse(`Request missing ${missingParams} parameters`);
   }
 };
diff --git a/src/types/types.ts b/src/types/types.ts
index 31a2493..c4634a7 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -203,23 +203,16 @@ export const detailsSchema = z.object({
   id: z.string().refine((val) => val !== "", {
     message: "ID cannot be an empty string",
   }),
-  documentType: z.string().refine(
-    (val) => {
-      return [
-        "experts",
-        "institutions",
-        "datasets",
-        "documents",
-        "trainings",
-        "projects",
-        "software",
-        "instruments",
-      ].includes(val);
-    },
-    {
-      message: "Invalid document type",
-    }
-  ),
+  documentType: z.union([
+    z.literal("experts"),
+    z.literal("institutions"),
+    z.literal("datasets"),
+    z.literal("documents"),
+    z.literal("trainings"),
+    z.literal("projects"),
+    z.literal("software"),
+    z.literal("instruments"),
+  ]),
 });
 
 export type detailsParamsType = z.infer<typeof detailsSchema>;
-- 
GitLab


From 7880876a112420f53cb9d4a85712a578f73a9e14 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 19 Mar 2025 12:37:53 +0100
Subject: [PATCH 43/55] covered the test case of mismatched params giving empty
 solr search

---
 .../20.misformedIdCorrectDocType.json         | 33 ++++++++++++
 .../21.correctIdMismatchedDocType.json        | 33 ++++++++++++
 src/app/api/__tests__/api/details.test.ts     | 52 +++++++++++--------
 .../20.misformedIdCorrectDocType.json         |  5 ++
 .../21.correctIdMismatchedDocType.json        |  5 ++
 src/app/api/details/route.ts                  |  9 +++-
 src/app/api/utils/shared.ts                   |  1 +
 7 files changed, 113 insertions(+), 25 deletions(-)
 create mode 100644 src/app/api/__tests__/__mocks__/solrResults/20.misformedIdCorrectDocType.json
 create mode 100644 src/app/api/__tests__/__mocks__/solrResults/21.correctIdMismatchedDocType.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/20.misformedIdCorrectDocType.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/21.correctIdMismatchedDocType.json

diff --git a/src/app/api/__tests__/__mocks__/solrResults/20.misformedIdCorrectDocType.json b/src/app/api/__tests__/__mocks__/solrResults/20.misformedIdCorrectDocType.json
new file mode 100644
index 0000000..8a5c278
--- /dev/null
+++ b/src/app/api/__tests__/__mocks__/solrResults/20.misformedIdCorrectDocType.json
@@ -0,0 +1,33 @@
+{
+  "responseHeader": {
+    "status": 0,
+    "QTime": 0,
+    "params": {
+      "q": "id:1234567890",
+      "defType": "edismax",
+      "indent": "true",
+      "qf": "name^4 txt_keywords^2 text",
+      "q.op": "OR",
+      "fq": [
+        "+type:Thesis",
+        "+type:DigitalDocument",
+        "+type:ScholarlyArticle",
+        "+type:Report",
+        "+type:Book",
+        "+type:Chapter",
+        "+type:Article"
+      ],
+      "sort": "score desc, indexed_ts desc",
+      "facet": "true",
+      "_": "1742381216058"
+    }
+  },
+  "response": { "numFound": 0, "start": 0, "numFoundExact": true, "docs": [] },
+  "facet_counts": {
+    "facet_queries": {},
+    "facet_fields": {},
+    "facet_ranges": {},
+    "facet_intervals": {},
+    "facet_heatmaps": {}
+  }
+}
diff --git a/src/app/api/__tests__/__mocks__/solrResults/21.correctIdMismatchedDocType.json b/src/app/api/__tests__/__mocks__/solrResults/21.correctIdMismatchedDocType.json
new file mode 100644
index 0000000..483b2c9
--- /dev/null
+++ b/src/app/api/__tests__/__mocks__/solrResults/21.correctIdMismatchedDocType.json
@@ -0,0 +1,33 @@
+{
+  "responseHeader": {
+    "status": 0,
+    "QTime": 0,
+    "params": {
+      "q": "id:https://doi.org/10.5880/gfz.4.8.2024.008",
+      "defType": "edismax",
+      "indent": "true",
+      "qf": "name^4 txt_keywords^2 text",
+      "q.op": "OR",
+      "fq": [
+        "+type:Thesis",
+        "+type:DigitalDocument",
+        "+type:ScholarlyArticle",
+        "+type:Report",
+        "+type:Book",
+        "+type:Chapter",
+        "+type:Article"
+      ],
+      "sort": "score desc, indexed_ts desc",
+      "facet": "true",
+      "_": "1742381216058"
+    }
+  },
+  "response": { "numFound": 0, "start": 0, "numFoundExact": true, "docs": [] },
+  "facet_counts": {
+    "facet_queries": {},
+    "facet_fields": {},
+    "facet_ranges": {},
+    "facet_intervals": {},
+    "facet_heatmaps": {}
+  }
+}
diff --git a/src/app/api/__tests__/api/details.test.ts b/src/app/api/__tests__/api/details.test.ts
index 5092615..55f56ed 100644
--- a/src/app/api/__tests__/api/details.test.ts
+++ b/src/app/api/__tests__/api/details.test.ts
@@ -2,6 +2,8 @@ import { NextRequest } from "next/server";
 
 import solrdocumentResponse from "@api/__tests__/__mocks__/solrResults/12.documentSource.json";
 import solrDatasetResponse from "@api/__tests__/__mocks__/solrResults/13.datasetSource.json";
+import solrMisformedIdCorrectDocType from "@api/__tests__/__mocks__/solrResults/20.misformedIdCorrectDocType.json";
+import solrCorrectIdMismatchedDocType from "@api/__tests__/__mocks__/solrResults/21.correctIdMismatchedDocType.json";
 import documentSource from "@api/__tests__/expectedApiResults/12.documentSource.json";
 import datasetSource from "@api/__tests__/expectedApiResults/13.datasetSource.json";
 import missingId from "@api/__tests__/expectedApiResults/15.missingId.json";
@@ -9,6 +11,8 @@ import missingDocumentType from "@api/__tests__/expectedApiResults/16.missingDoc
 import missingParams from "@api/__tests__/expectedApiResults/17.missingParams.json";
 import invalidDocType from "@api/__tests__/expectedApiResults/18.invalidDocType.json";
 import emptyStringId from "@api/__tests__/expectedApiResults/19.emptyStringId.json";
+import misformedIdCorrectDocType from "@api/__tests__/expectedApiResults/20.misformedIdCorrectDocType.json";
+import correctIdMismatchedDocType from "@api/__tests__/expectedApiResults/21.correctIdMismatchedDocType.json";
 import { GET } from "@api/details/route";
 
 describe("unit tests for /details API Endpoint", () => {
@@ -20,7 +24,7 @@ describe("unit tests for /details API Endpoint", () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("documentType", "documents");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
     expect(jsonResult).toMatchObject(missingId);
@@ -30,7 +34,7 @@ describe("unit tests for /details API Endpoint", () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
     expect(jsonResult).toMatchObject(missingDocumentType);
@@ -39,7 +43,7 @@ describe("unit tests for /details API Endpoint", () => {
   it("17.should return an error when both ID and documentType are not passed as a param", async () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
     expect(jsonResult).toMatchObject(missingParams);
@@ -50,7 +54,7 @@ describe("unit tests for /details API Endpoint", () => {
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
     req.nextUrl.searchParams.append("documentType", "documen");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
     expect(jsonResult).toMatchObject(invalidDocType);
@@ -61,40 +65,42 @@ describe("unit tests for /details API Endpoint", () => {
     req.nextUrl.searchParams.append("id", "");
     req.nextUrl.searchParams.append("documentType", "documents");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
     expect(jsonResult).toMatchObject(emptyStringId);
   });
 
-  it.skip("20.should return an error on being given an misformed id and correct documentType", async () => {
+  it("20.should return an error on being given an misformed id and correct documentType", async () => {
+    jest.spyOn(global, "fetch").mockImplementationOnce(() =>
+      Promise.resolve({
+        json: () => Promise.resolve(solrMisformedIdCorrectDocType),
+      } as Response)
+    );
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "1234567890");
     req.nextUrl.searchParams.append("documentType", "documents");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
-    expect(jsonResult).toMatchObject({
-      error: {
-        message: "No results found for given ID and documentType",
-      },
-    });
+    expect(jsonResult).toMatchObject(misformedIdCorrectDocType);
   });
 
-  it.skip("21.should return an error on being given an correct id and incorrect documentType", async () => {
+  it("21.should return an error on being given an correct id and incorrect documentType", async () => {
+    jest.spyOn(global, "fetch").mockImplementationOnce(() =>
+      Promise.resolve({
+        json: () => Promise.resolve(solrCorrectIdMismatchedDocType),
+      } as Response)
+    );
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5880/gfz.4.8.2024.008");
     req.nextUrl.searchParams.append("documentType", "documents");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(400);
-    expect(jsonResult).toMatchObject({
-      error: {
-        message: "No results found for given ID and documentType",
-      },
-    });
+    expect(jsonResult).toMatchObject(correctIdMismatchedDocType);
   });
 
   it.skip("22.should return result item for given documentType and ID", async () => {
@@ -107,7 +113,7 @@ describe("unit tests for /details API Endpoint", () => {
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://doi.org/10.5281/zenodo.14945361");
     req.nextUrl.searchParams.append("documentType", "software");
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(200);
     expect(jsonResult).toMatchObject(documentSource);
@@ -124,7 +130,7 @@ describe("unit tests for /details API Endpoint", () => {
     req.nextUrl.searchParams.append("id", "https://doi.org/10.13039/100009133");
     req.nextUrl.searchParams.append("documentType", "institutions");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(200);
     expect(jsonResult).toMatchObject(datasetSource);
@@ -141,7 +147,7 @@ describe("unit tests for /details API Endpoint", () => {
     req.nextUrl.searchParams.append("id", "https://ror.org/04aj4c181");
     req.nextUrl.searchParams.append("documentType", "institutions");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(200);
     expect(jsonResult).toMatchObject(datasetSource);
@@ -158,7 +164,7 @@ describe("unit tests for /details API Endpoint", () => {
     req.nextUrl.searchParams.append("id", "https://ror.org/0281dp749");
     req.nextUrl.searchParams.append("documentType", "institutions");
 
-    const response = await GET(req);
+    const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(200);
     expect(jsonResult).toMatchObject(datasetSource);
diff --git a/src/app/api/__tests__/expectedApiResults/20.misformedIdCorrectDocType.json b/src/app/api/__tests__/expectedApiResults/20.misformedIdCorrectDocType.json
new file mode 100644
index 0000000..9181115
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/20.misformedIdCorrectDocType.json
@@ -0,0 +1,5 @@
+{
+  "error": {
+    "message": "No results found for given ID and documentType"
+  }
+}
diff --git a/src/app/api/__tests__/expectedApiResults/21.correctIdMismatchedDocType.json b/src/app/api/__tests__/expectedApiResults/21.correctIdMismatchedDocType.json
new file mode 100644
index 0000000..9181115
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/21.correctIdMismatchedDocType.json
@@ -0,0 +1,5 @@
+{
+  "error": {
+    "message": "No results found for given ID and documentType"
+  }
+}
diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 693cc4c..96d8164 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -22,8 +22,8 @@ export const GET = async (req: NextRequest) => {
 
     const { id, documentType }: detailsParamsType = requestBody.data;
     const searchText = `id:${id}`;
-    // build SOLR query, query the SOLR instance for data
     const { facetIntervalFields, queryFacetFields } = createFacetParams(documentType);
+
     const solrResponse: SolrResponseType = await new SolrQuery(
       SOLR_QUERY_DEFAULTS.start,
       SOLR_QUERY_DEFAULTS.rows,
@@ -35,7 +35,12 @@ export const GET = async (req: NextRequest) => {
       documentType
     ).json();
 
-    console.log("solrResponse", solrResponse);
+    if (solrResponse?.response?.numFound === 0) {
+      return Response.json(
+        { error: { message: "No results found for given ID and documentType" } },
+        { status: 400 }
+      );
+    }
 
     // // create the response object in the desired shape
     // const responseRecords: ResultItem[] = solrResponse.response.docs.map(
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index 5ace810..1a68e55 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -192,6 +192,7 @@ export const handleDetailsParamErrors = (errors: ZodIssue[]) => {
     if (errorMessage) return errorResponse(errorMessage);
   }
 
+  // TODO: Is the following check even required?
   const isMultiParamError =
     errors.length > 1 &&
     errors.every(
-- 
GitLab


From 4ac986a3fac202d620f693dd255b5338c95279b2 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 19 Mar 2025 15:11:08 +0100
Subject: [PATCH 44/55] testing functionality that provides plain solr result
 item

---
 .../solrResults/22.softwareDetails.json       | 70 +++++++++++++++++++
 src/app/api/__tests__/api/details.test.ts     |  8 +--
 .../22.softwareDetails.json                   | 34 +++++++++
 src/app/api/details/route.ts                  | 44 +++++-------
 4 files changed, 127 insertions(+), 29 deletions(-)
 create mode 100644 src/app/api/__tests__/__mocks__/solrResults/22.softwareDetails.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/22.softwareDetails.json

diff --git a/src/app/api/__tests__/__mocks__/solrResults/22.softwareDetails.json b/src/app/api/__tests__/__mocks__/solrResults/22.softwareDetails.json
new file mode 100644
index 0000000..018306f
--- /dev/null
+++ b/src/app/api/__tests__/__mocks__/solrResults/22.softwareDetails.json
@@ -0,0 +1,70 @@
+{
+  "responseHeader": {
+    "status": 0,
+    "QTime": 0,
+    "params": {
+      "q": "id:https://doi.org/10.5281/zenodo.14945361",
+      "defType": "edismax",
+      "indent": "true",
+      "qf": "name^4 txt_keywords^2 text",
+      "q.op": "OR",
+      "fq": "+type:(SoftwareSourceCode SoftwareApplication SoftwareLibrary WebApplication CommandlineApplication)",
+      "sort": "score desc, indexed_ts desc",
+      "_": "1742384819166"
+    }
+  },
+  "response": {
+    "numFound": 1,
+    "start": 0,
+    "numFoundExact": true,
+    "docs": [
+      {
+        "id": "https://doi.org/10.5281/zenodo.14945361",
+        "type": "SoftwareSourceCode",
+        "id_author": [
+          "0000-0001-5910-8081",
+          "0000-0002-2651-1293",
+          "0000-0002-3365-8146",
+          "0000-0002-3427-8188",
+          "0009-0002-8280-3554",
+          "0009-0007-0571-6429"
+        ],
+        "txt_author": [
+          "Antonia Anna Jost",
+          "Boris Shapkin",
+          "Dmitrii Pantiukhin",
+          "Ivan Kuznetsov",
+          "Nikolay V. Koldunov",
+          "Thomas Jung"
+        ],
+        "txt_datePublished": ["2025-02-28"],
+        "description": "ClimSight is an advanced tool that integrates Large Language Models (LLMs) with climate data to provide localized climate insights for decision-making. ClimSight transforms complex climate data into actionable insights for agriculture, urban planning, disaster management, and policy development.\n\nThe target audience includes researchers, providers of climate services, policymakers, agricultural planners, urban developers, and other stakeholders who require detailed climate information to support decision-making. ClimSight is designed to democratize access to climate data, empowering users with insights relevant to their specific contexts.\n\nClimSight distinguishes itself through several key advancements:\n\n\n\nIntegration of LLMs: ClimSight leverages state-of-the-art LLMs to interpret complex climate-related queries, synthesizing information from diverse data sources.\n\nMulti-Source Data Integration: Unlike conventional systems that rely solely on structured climate data, ClimSight integrates information from multiple sources.\n\nEvidence-Based Approach: ClimSight ensures contextually accurate answers by retrieving relevant knowledge from scientific reports, IPCC documents, and geographical databases.\n\nModular Architecture: Specialized components handle distinct tasks, such as data retrieval, contextual understanding, and result synthesis, leading to more accurate outputs.\n\nReal-World Applications: ClimSight is validated through practical examples, such as assessing climate risks for specific agricultural activities and urban planning scenarios.\n\n\nAcknowledgementsThis work was supported by the European Union’s Destination Earth Initiative and relates to tasks entrusted by the European Union to the European Centre for Medium-Range Weather Forecasts, implementing part of this Initiative with funding by the European Union. We also thank the Helmholtz Association and the Federal Ministry of Education and Research (BMBF) for supporting the DataHub Initiative of the Research Field Earth and Environment, which contributed to this study. Additionally, this work is supported by project S1: Diagnosis and Metrics in Climate Models of the Collaborative Research Centre TRR 181 “Energy Transfer in Atmosphere and Ocean,” funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation, project no. 274762653). Views and opinions expressed are those of the authors only and do not necessarily reflect those of the European Union or the European Climate Infrastructure and Environment Executive Agency (CINEA). Neither the European Union nor the granting authority can be held responsible for them.",
+        "name": "ClimSight: Transforming Climate Services with LLMs and Multi-Source Data Integration",
+        "txt_provider": ["datacite"],
+        "txt_publisher": ["Zenodo"],
+        "txt_schemaVersion": ["http://datacite.org/schema/kernel-4"],
+        "txt_url": ["https://zenodo.org/doi/10.5281/zenodo.14945361"],
+        "txt_version": ["v1.0.0"],
+        "keys": [
+          "id",
+          "type",
+          "id_author",
+          "txt_author",
+          "txt_datePublished",
+          "description",
+          "name",
+          "txt_provider",
+          "txt_publisher",
+          "txt_schemaVersion",
+          "txt_url",
+          "txt_version"
+        ],
+        "json_source": "{\"@context\": \"http://schema.org\", \"@id\": \"https://doi.org/10.5281/zenodo.14945361\", \"@type\": \"SoftwareSourceCode\", \"additionalType\": \"\", \"author\": [{\"@id\": \"0000-0001-5910-8081\", \"@type\": \"Person\", \"affiliation\": {\"@id\": \"https://ror.org/032e6b942\", \"@type\": \"Organization\", \"name\": \"Alfred-Wegener-Institut Helmholtz-Zentrum f\\u00fcr Polar- und Meeresforschung\"}, \"familyName\": \"Kuznetsov\", \"givenName\": \"Ivan\", \"name\": \"Ivan Kuznetsov\"}, {\"@id\": \"0009-0007-0571-6429\", \"@type\": \"Person\", \"affiliation\": {\"@id\": \"edmo:1368\", \"@type\": \"Organization\", \"name\": \"Alfred Wegener Institute Helmholtz Centre for Polar and Marine Research\"}, \"familyName\": \"Jost\", \"givenName\": \"Antonia Anna\", \"name\": \"Antonia Anna Jost\"}, {\"@id\": \"0000-0002-3427-8188\", \"@type\": \"Person\", \"affiliation\": {\"@id\": \"https://ror.org/032e6b942\", \"@type\": \"Organization\", \"name\": \"Alfred-Wegener-Institut Helmholtz-Zentrum f\\u00fcr Polar- und Meeresforschung\"}, \"familyName\": \"Pantiukhin\", \"givenName\": \"Dmitrii\", \"name\": \"Dmitrii Pantiukhin\"}, {\"@id\": \"0009-0002-8280-3554\", \"@type\": \"Person\", \"affiliation\": {\"@id\": \"edmo:1368\", \"@type\": \"Organization\", \"name\": \"Alfred Wegener Institute Helmholtz Centre for Polar and Marine Research\"}, \"familyName\": \"Shapkin\", \"givenName\": \"Boris\", \"name\": \"Boris Shapkin\"}, {\"@id\": \"0000-0002-2651-1293\", \"@type\": \"Person\", \"affiliation\": [{\"@type\": \"Organization\", \"name\": \"University of Bremen\"}, {\"@id\": \"https://ror.org/032e6b942\", \"@type\": \"Organization\", \"name\": \"Alfred-Wegener-Institut Helmholtz-Zentrum f\\u00fcr Polar- und Meeresforschung\"}], \"familyName\": \"Jung\", \"givenName\": \"Thomas\", \"name\": \"Thomas Jung\"}, {\"@id\": \"0000-0002-3365-8146\", \"@type\": \"Person\", \"affiliation\": {\"@id\": \"https://ror.org/032e6b942\", \"@type\": \"Organization\", \"name\": \"Alfred-Wegener-Institut Helmholtz-Zentrum f\\u00fcr Polar- und Meeresforschung\"}, \"familyName\": \"Koldunov\", \"givenName\": \"Nikolay V.\", \"name\": \"Nikolay V. Koldunov\"}], \"datePublished\": \"2025-02-28\", \"description\": \"ClimSight is an advanced tool that integrates Large Language Models (LLMs) with climate data to provide localized climate insights for decision-making. ClimSight transforms complex climate data into actionable insights for agriculture, urban planning, disaster management, and policy development.\\n\\nThe target audience includes researchers, providers of climate services, policymakers, agricultural planners, urban developers, and other stakeholders who require detailed climate information to support decision-making. ClimSight is designed to democratize access to climate data, empowering users with insights relevant to their specific contexts.\\n\\nClimSight distinguishes itself through several key advancements:\\n\\n\\n\\nIntegration of LLMs: ClimSight leverages state-of-the-art LLMs to interpret complex climate-related queries, synthesizing information from diverse data sources.\\n\\nMulti-Source Data Integration: Unlike conventional systems that rely solely on structured climate data, ClimSight integrates information from multiple sources.\\n\\nEvidence-Based Approach: ClimSight ensures contextually accurate answers by retrieving relevant knowledge from scientific reports, IPCC documents, and geographical databases.\\n\\nModular Architecture: Specialized components handle distinct tasks, such as data retrieval, contextual understanding, and result synthesis, leading to more accurate outputs.\\n\\nReal-World Applications: ClimSight is validated through practical examples, such as assessing climate risks for specific agricultural activities and urban planning scenarios.\\n\\n\\nAcknowledgementsThis work was supported by the European Union\\u2019s Destination Earth Initiative and relates to tasks entrusted by the European Union to the European Centre for Medium-Range Weather Forecasts, implementing part of this Initiative with funding by the European Union. We also thank the Helmholtz Association and the Federal Ministry of Education and Research (BMBF) for supporting the DataHub Initiative of the Research Field Earth and Environment, which contributed to this study. Additionally, this work is supported by project S1: Diagnosis and Metrics in Climate Models of the Collaborative Research Centre TRR 181 \\u201cEnergy Transfer in Atmosphere and Ocean,\\u201d funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation, project no. 274762653). Views and opinions expressed are those of the authors only and do not necessarily reflect those of the European Union or the European Climate Infrastructure and Environment Executive Agency (CINEA). Neither the European Union nor the granting authority can be held responsible for them.\", \"keywords\": [], \"name\": \"ClimSight: Transforming Climate Services with LLMs and Multi-Source Data Integration\", \"provider\": {\"@type\": \"Organization\", \"name\": \"datacite\"}, \"publisher\": {\"@type\": \"Organization\", \"name\": \"Zenodo\"}, \"schemaVersion\": \"http://datacite.org/schema/kernel-4\", \"url\": \"https://zenodo.org/doi/10.5281/zenodo.14945361\", \"version\": \"v1.0.0\"}",
+        "index_id": "4b444c90-82e2-46eb-8525-04816e250a6a",
+        "_version_": "1826639265757396992",
+        "indexed_ts": "2025-03-15T06:09:13.092Z",
+        "json_uplifted": "{\"@context\": \"http://schema.org\", \"@graph\": [{\"affiliation\": {\"id\": \"https://ror.org/032e6b942\"}, \"familyName\": \"Koldunov\", \"givenName\": \"Nikolay V.\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-3365-8146\", \"name\": \"Nikolay V. Koldunov\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_5/0dbcacb0a287730cfb8b2eb3a1b53e4d\", \"type\": \"Person\"}, {\"affiliation\": {\"id\": \"edmo:1368\"}, \"familyName\": \"Shapkin\", \"givenName\": \"Boris\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0009-0002-8280-3554\", \"name\": \"Boris Shapkin\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_3/5369fafd2172bacc53b09fc954ba3624\", \"type\": \"Person\"}, {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/publisher/d8ac2c95f46d79ce386f2aadd4053458\", \"name\": \"Zenodo\", \"type\": \"Organization\"}, {\"affiliation\": {\"id\": \"https://ror.org/032e6b942\"}, \"familyName\": \"Pantiukhin\", \"givenName\": \"Dmitrii\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-3427-8188\", \"name\": \"Dmitrii Pantiukhin\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_2/5fcd2254cc7f1aca0afa299645b8d203\", \"type\": \"Person\"}, {\"id\": \"edmo:1368\", \"name\": \"Alfred Wegener Institute Helmholtz Centre for Polar and Marine Research\", \"sameAs\": [\"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_1/affiliation/a7af5f12b070f67740eb30ee0f1eee44\", \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_3/affiliation/a7af5f12b070f67740eb30ee0f1eee44\"], \"type\": \"Organization\"}, {\"id\": \"https://ror.org/032e6b942\", \"name\": \"Alfred-Wegener-Institut Helmholtz-Zentrum f\\u00fcr Polar- und Meeresforschung\", \"sameAs\": [\"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_0/affiliation/b3fd32a5b279ca828319749bce483267\", \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_2/affiliation/b3fd32a5b279ca828319749bce483267\", \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_4/affiliation_1/b3fd32a5b279ca828319749bce483267\", \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_5/affiliation/b3fd32a5b279ca828319749bce483267\"], \"type\": \"Organization\"}, {\"affiliation\": {\"id\": \"edmo:1368\"}, \"familyName\": \"Jost\", \"givenName\": \"Antonia Anna\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0009-0007-0571-6429\", \"name\": \"Antonia Anna Jost\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_1/66b9706925b2aa07c92650a76e4a39f6\", \"type\": \"Person\"}, {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/provider/4c7b20ccf49c1dbb21a45b3c8ea32def\", \"name\": \"datacite\", \"type\": \"Organization\"}, {\"affiliation\": {\"id\": \"https://ror.org/032e6b942\"}, \"familyName\": \"Kuznetsov\", \"givenName\": \"Ivan\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0001-5910-8081\", \"name\": \"Ivan Kuznetsov\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_0/5da7dd46e48e13b92c322edc49ac3760\", \"type\": \"Person\"}, {\"additionalType\": \"\", \"author\": [{\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0001-5910-8081\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0009-0007-0571-6429\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-3427-8188\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0009-0002-8280-3554\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-2651-1293\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-3365-8146\"}], \"datePublished\": \"2025-02-28\", \"description\": \"ClimSight is an advanced tool that integrates Large Language Models (LLMs) with climate data to provide localized climate insights for decision-making. ClimSight transforms complex climate data into actionable insights for agriculture, urban planning, disaster management, and policy development.\\n\\nThe target audience includes researchers, providers of climate services, policymakers, agricultural planners, urban developers, and other stakeholders who require detailed climate information to support decision-making. ClimSight is designed to democratize access to climate data, empowering users with insights relevant to their specific contexts.\\n\\nClimSight distinguishes itself through several key advancements:\\n\\n\\n\\nIntegration of LLMs: ClimSight leverages state-of-the-art LLMs to interpret complex climate-related queries, synthesizing information from diverse data sources.\\n\\nMulti-Source Data Integration: Unlike conventional systems that rely solely on structured climate data, ClimSight integrates information from multiple sources.\\n\\nEvidence-Based Approach: ClimSight ensures contextually accurate answers by retrieving relevant knowledge from scientific reports, IPCC documents, and geographical databases.\\n\\nModular Architecture: Specialized components handle distinct tasks, such as data retrieval, contextual understanding, and result synthesis, leading to more accurate outputs.\\n\\nReal-World Applications: ClimSight is validated through practical examples, such as assessing climate risks for specific agricultural activities and urban planning scenarios.\\n\\n\\nAcknowledgementsThis work was supported by the European Union\\u2019s Destination Earth Initiative and relates to tasks entrusted by the European Union to the European Centre for Medium-Range Weather Forecasts, implementing part of this Initiative with funding by the European Union. We also thank the Helmholtz Association and the Federal Ministry of Education and Research (BMBF) for supporting the DataHub Initiative of the Research Field Earth and Environment, which contributed to this study. Additionally, this work is supported by project S1: Diagnosis and Metrics in Climate Models of the Collaborative Research Centre TRR 181 \\u201cEnergy Transfer in Atmosphere and Ocean,\\u201d funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation, project no. 274762653). Views and opinions expressed are those of the authors only and do not necessarily reflect those of the European Union or the European Climate Infrastructure and Environment Executive Agency (CINEA). Neither the European Union nor the granting authority can be held responsible for them.\", \"id\": \"https://doi.org/10.5281/zenodo.14945361\", \"name\": \"ClimSight: Transforming Climate Services with LLMs and Multi-Source Data Integration\", \"provider\": {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/provider/4c7b20ccf49c1dbb21a45b3c8ea32def\"}, \"publisher\": {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/publisher/d8ac2c95f46d79ce386f2aadd4053458\"}, \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/4d04ebb5af408eda5a3fd1df7092b566\", \"schemaVersion\": \"http://datacite.org/schema/kernel-4\", \"type\": \"SoftwareSourceCode\", \"url\": \"https://zenodo.org/doi/10.5281/zenodo.14945361\", \"version\": \"v1.0.0\"}, {\"affiliation\": [{\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_4/affiliation_0/991d8a30f481e45eb4a441593dbb272c\"}, {\"id\": \"https://ror.org/032e6b942\"}], \"familyName\": \"Jung\", \"givenName\": \"Thomas\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-2651-1293\", \"name\": \"Thomas Jung\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_4/0984d92a1f9f043a206e17ece49f301b\", \"type\": \"Person\"}, {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/c3d6218cfef00/author_4/affiliation_0/991d8a30f481e45eb4a441593dbb272c\", \"name\": \"University of Bremen\", \"type\": \"Organization\"}]}"
+      }
+    ]
+  }
+}
diff --git a/src/app/api/__tests__/api/details.test.ts b/src/app/api/__tests__/api/details.test.ts
index 55f56ed..3bd614b 100644
--- a/src/app/api/__tests__/api/details.test.ts
+++ b/src/app/api/__tests__/api/details.test.ts
@@ -1,10 +1,9 @@
 import { NextRequest } from "next/server";
 
-import solrdocumentResponse from "@api/__tests__/__mocks__/solrResults/12.documentSource.json";
 import solrDatasetResponse from "@api/__tests__/__mocks__/solrResults/13.datasetSource.json";
 import solrMisformedIdCorrectDocType from "@api/__tests__/__mocks__/solrResults/20.misformedIdCorrectDocType.json";
 import solrCorrectIdMismatchedDocType from "@api/__tests__/__mocks__/solrResults/21.correctIdMismatchedDocType.json";
-import documentSource from "@api/__tests__/expectedApiResults/12.documentSource.json";
+import solrSoftwareDetails from "@api/__tests__/__mocks__/solrResults/22.softwareDetails.json";
 import datasetSource from "@api/__tests__/expectedApiResults/13.datasetSource.json";
 import missingId from "@api/__tests__/expectedApiResults/15.missingId.json";
 import missingDocumentType from "@api/__tests__/expectedApiResults/16.missingDocumentType.json";
@@ -13,6 +12,7 @@ import invalidDocType from "@api/__tests__/expectedApiResults/18.invalidDocType.
 import emptyStringId from "@api/__tests__/expectedApiResults/19.emptyStringId.json";
 import misformedIdCorrectDocType from "@api/__tests__/expectedApiResults/20.misformedIdCorrectDocType.json";
 import correctIdMismatchedDocType from "@api/__tests__/expectedApiResults/21.correctIdMismatchedDocType.json";
+import softwareDetails from "@api/__tests__/expectedApiResults/22.softwareDetails.json";
 import { GET } from "@api/details/route";
 
 describe("unit tests for /details API Endpoint", () => {
@@ -106,7 +106,7 @@ describe("unit tests for /details API Endpoint", () => {
   it.skip("22.should return result item for given documentType and ID", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
-        json: () => Promise.resolve(solrdocumentResponse),
+        json: () => Promise.resolve(solrSoftwareDetails),
       } as Response)
     );
 
@@ -116,7 +116,7 @@ describe("unit tests for /details API Endpoint", () => {
     const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(200);
-    expect(jsonResult).toMatchObject(documentSource);
+    expect(jsonResult).toMatchObject(softwareDetails);
   });
 
   it.skip("23.should return result item for the institute with given ID, without any ROR enrichment", async () => {
diff --git a/src/app/api/__tests__/expectedApiResults/22.softwareDetails.json b/src/app/api/__tests__/expectedApiResults/22.softwareDetails.json
new file mode 100644
index 0000000..62e4399
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/22.softwareDetails.json
@@ -0,0 +1,34 @@
+{
+  "id": "https://doi.org/10.5281/zenodo.14945361",
+  "type": "SoftwareSourceCode",
+  "txt_author": [
+    "Antonia Anna Jost",
+    "Boris Shapkin",
+    "Dmitrii Pantiukhin",
+    "Ivan Kuznetsov",
+    "Nikolay V. Koldunov",
+    "Thomas Jung"
+  ],
+  "description": "ClimSight is an advanced tool that integrates Large Language Models (LLMs) with climate data to provide localized climate insights for decision-making. ClimSight transforms complex climate data into actionable insights for agriculture, urban planning, disaster management, and policy development.\n\n      The target audience includes researchers, providers of climate services, policymakers, agricultural planners, urban developers, and other stakeholders who require detailed climate information to support decision-making. ClimSight is designed to democratize access to climate data, empowering users with insights relevant to their specific contexts.\n\n      ClimSight distinguishes itself through several key advancements:\n\n      Integration of LLMs: ClimSight leverages state-of-the-art LLMs to interpret complex climate-related queries, synthesizing information from diverse data sources.\n\n      Multi-Source Data Integration: Unlike conventional systems that rely solely on structured climate data, ClimSight integrates information from multiple sources.\n\n      Evidence-Based Approach: ClimSight ensures contextually accurate answers by retrieving relevant knowledge from scientific reports, IPCC documents, and geographical databases.\n\n      Modular Architecture: Specialized components handle distinct tasks, such as data retrieval, contextual understanding, and result synthesis, leading to more accurate outputs.\n\n      Real-World Applications: ClimSight is validated through practical examples, such as assessing climate risks for specific agricultural activities and urban planning scenarios.\n\n      AcknowledgementsThis work was supported by the European Union's Destination Earth Initiative and relates to tasks entrusted by the European Union to the European Centre for Medium-Range Weather Forecasts, implementing part of this Initiative with funding by the European Union. We also thank the Helmholtz Association and the Federal Ministry of Education and Research (BMBF) for supporting the DataHub Initiative of the Research Field Earth and Environment, which contributed to this study. Additionally, this work is supported by project S1: Diagnosis and Metrics in Climate Models of the Collaborative Research Centre TRR 181 .Energy Transfer in Atmosphere and Ocean, funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation, project no. 274762653). Views and opinions expressed are those of the authors only and do not necessarily reflect those of the European Union or the European Climate Infrastructure and Environment Executive Agency (CINEA). Neither the European Union nor the granting authority can be held responsible for them.",
+  "name": "ClimSight: Transforming Climate Services with LLMs and Multi-Source Data Integration",
+  "txt_provider": ["datacite"],
+  "txt_publisher": ["Zenodo"],
+  "txt_url": ["https://zenodo.org/doi/10.5281/zenodo.14945361"],
+  "txt_version": ["v1.0.0"],
+  "keys": [
+    "id",
+    "type",
+    "txt_author",
+    "description",
+    "name",
+    "txt_provider",
+    "txt_publisher",
+    "txt_url",
+    "txt_version"
+  ],
+  "recordConfig": {
+    "index_id": "4b444c90-82e2-46eb-8525-04816e250a6a",
+    "_version_": "1826639265757396992",
+    "indexed_ts": "2025-03-15T06:09:13.092Z"
+  }
+}
diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 96d8164..db0ec92 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -1,9 +1,16 @@
 import { type NextRequest } from "next/server";
 
-import { detailsParamsType, detailsSchema, SolrResponseType } from "@/types/types";
+import {
+  detailsParamsType,
+  detailsSchema,
+  ResultItem,
+  SolrResponseDocsType,
+  SolrResponseType,
+} from "@/types/types";
 import { SOLR_QUERY_DEFAULTS } from "@api/config/config";
 import {
   createFacetParams,
+  createResultItem,
   createSearchParamsMap,
   handleDetailsParamErrors,
 } from "@api/utils/shared";
@@ -40,31 +47,18 @@ export const GET = async (req: NextRequest) => {
         { error: { message: "No results found for given ID and documentType" } },
         { status: 400 }
       );
+    } else {
+      const solrResponseRecord: ResultItem[] = solrResponse.response.docs.map(
+        (record: SolrResponseDocsType) => createResultItem(record)
+      );
+      console.log(solrResponseRecord[0]);
+      if (documentType === "institutions") {
+        // TODO: add ROR enrichment & logo enrichment
+        return Response.json(solrResponseRecord[0], { status: 200 });
+      } else {
+        return Response.json(solrResponseRecord[0], { status: 200 });
+      }
     }
-
-    // // create the response object in the desired shape
-    // const responseRecords: ResultItem[] = solrResponse.response.docs.map(
-    //   (record: SolrResponseDocsType) => createResultItem(record)
-    // );
-
-    // const responseTotalCount = solrResponse.response.numFound;
-
-    // const categoryCounts = updateCategoryCountsForSearch(
-    //   getSolrCategoryCountsMap(solrResponse.facet_counts.facet_fields.type)
-    // );
-
-    // const responseFilters = includeFacets
-    //   ? createResultFilters(solrResponse.facet_counts.facet_fields)
-    //   : [];
-
-    // const response: SearchResponse = {
-    //   records: responseRecords,
-    //   totalCount: responseTotalCount,
-    //   categoryCounts,
-    //   filters: responseFilters,
-    // };
-
-    // return Response.json(response);
   } catch (error) {
     console.error("Error while handling details", error);
     return Response.json(
-- 
GitLab


From da19108977fb216c94446cbc73d9ffd883c1a462 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 20 Mar 2025 12:18:53 +0100
Subject: [PATCH 45/55] got all test cases for details api to pass, first
 completely working draft of details api written

---
 .../rorResults/24.rorWithoutLogo.json         |  98 ++++++++
 .../__mocks__/rorResults/25.rorWithLogo.json  | 213 +++++++++++++++++
 .../solrResults/23.institutionWithoutRor.json |  34 +++
 .../24.institutionWithRorWithoutLogo.json     |  34 +++
 .../25.institutionWithRorWithLogo.json        |  34 +++
 src/app/api/__tests__/api/details.test.ts     |  56 +++--
 .../22.softwareDetails.json                   |   2 +-
 .../23.institutionWithoutRor.json             |  11 +
 .../24.institutionWithRorWithoutLogo.json     | 105 +++++++++
 .../25.institutionWithRorWithLogo.json        | 222 ++++++++++++++++++
 src/app/api/details/route.ts                  |  50 +++-
 src/types/types.ts                            |   7 +-
 12 files changed, 838 insertions(+), 28 deletions(-)
 create mode 100644 src/app/api/__tests__/__mocks__/rorResults/24.rorWithoutLogo.json
 create mode 100644 src/app/api/__tests__/__mocks__/rorResults/25.rorWithLogo.json
 create mode 100644 src/app/api/__tests__/__mocks__/solrResults/23.institutionWithoutRor.json
 create mode 100644 src/app/api/__tests__/__mocks__/solrResults/24.institutionWithRorWithoutLogo.json
 create mode 100644 src/app/api/__tests__/__mocks__/solrResults/25.institutionWithRorWithLogo.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/23.institutionWithoutRor.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/24.institutionWithRorWithoutLogo.json
 create mode 100644 src/app/api/__tests__/expectedApiResults/25.institutionWithRorWithLogo.json

diff --git a/src/app/api/__tests__/__mocks__/rorResults/24.rorWithoutLogo.json b/src/app/api/__tests__/__mocks__/rorResults/24.rorWithoutLogo.json
new file mode 100644
index 0000000..4910282
--- /dev/null
+++ b/src/app/api/__tests__/__mocks__/rorResults/24.rorWithoutLogo.json
@@ -0,0 +1,98 @@
+{
+  "id": "https://ror.org/04aj4c181",
+  "name": "Technische Informationsbibliothek (TIB)",
+  "status": "active",
+  "email_address": null,
+  "ip_addresses": [],
+  "established": 1959,
+  "types": ["Archive"],
+  "relationships": [
+    {
+      "label": "Leibniz Association",
+      "type": "Parent",
+      "id": "https://ror.org/01n6r0e97"
+    },
+    {
+      "label": "TIB Open Publishing",
+      "type": "Child",
+      "id": "https://ror.org/058nncw69"
+    }
+  ],
+  "addresses": [
+    {
+      "lat": 52.37052,
+      "lng": 9.73322,
+      "state": null,
+      "state_code": null,
+      "city": "Hanover",
+      "geonames_city": {
+        "id": 2910831,
+        "city": "Hanover",
+        "geonames_admin1": {
+          "name": "Lower Saxony",
+          "id": null,
+          "ascii_name": null,
+          "code": "DE.NI"
+        },
+        "geonames_admin2": {
+          "name": null,
+          "id": null,
+          "ascii_name": null,
+          "code": null
+        },
+        "license": {
+          "attribution": "Data from geonames.org under a CC-BY 3.0 license",
+          "license": "http://creativecommons.org/licenses/by/3.0/"
+        },
+        "nuts_level1": {
+          "name": null,
+          "code": null
+        },
+        "nuts_level2": {
+          "name": null,
+          "code": null
+        },
+        "nuts_level3": {
+          "name": null,
+          "code": null
+        }
+      },
+      "postcode": null,
+      "primary": false,
+      "line": null,
+      "country_geonames_id": null
+    }
+  ],
+  "links": ["https://www.tib.eu/en/"],
+  "aliases": [
+    "German National Library of Science and Technology",
+    "German National Library of Science and Technology (TIB) - Leibniz Information Centre for Science and Technology - University Library",
+    "Technische Informationsbibliothek (TIB) - Leibniz-Informationszentrum Technik und Naturwissenschaften - Universitätsbibliothek"
+  ],
+  "acronyms": ["TIB"],
+  "wikipedia_url": "https://en.wikipedia.org/wiki/German_National_Library_of_Science_and_Technology",
+  "labels": [
+    {
+      "label": "Technische Informationsbibliothek",
+      "iso639": "de"
+    }
+  ],
+  "country": {
+    "country_name": "Germany",
+    "country_code": "DE"
+  },
+  "external_ids": {
+    "ISNI": {
+      "preferred": null,
+      "all": ["0000 0001 2174 6694"]
+    },
+    "Wikidata": {
+      "preferred": null,
+      "all": ["Q2399120"]
+    },
+    "GRID": {
+      "preferred": "grid.461819.3",
+      "all": "grid.461819.3"
+    }
+  }
+}
diff --git a/src/app/api/__tests__/__mocks__/rorResults/25.rorWithLogo.json b/src/app/api/__tests__/__mocks__/rorResults/25.rorWithLogo.json
new file mode 100644
index 0000000..b8e7620
--- /dev/null
+++ b/src/app/api/__tests__/__mocks__/rorResults/25.rorWithLogo.json
@@ -0,0 +1,213 @@
+{
+  "id": "https://ror.org/0281dp749",
+  "name": "Helmholtz Association of German Research Centres",
+  "status": "active",
+  "email_address": null,
+  "ip_addresses": [],
+  "established": 1995,
+  "types": ["Funder", "Government"],
+  "relationships": [
+    {
+      "label": "Alfred-Wegener-Institut Helmholtz-Zentrum für Polar- und Meeresforschung",
+      "type": "Child",
+      "id": "https://ror.org/032e6b942"
+    },
+    {
+      "label": "Deutsches Elektronen-Synchrotron DESY",
+      "type": "Child",
+      "id": "https://ror.org/01js2sh04"
+    },
+    {
+      "label": "Forschungszentrum Jülich",
+      "type": "Child",
+      "id": "https://ror.org/02nv7yv05"
+    },
+    {
+      "label": "GEOMAR Helmholtz Centre for Ocean Research Kiel",
+      "type": "Child",
+      "id": "https://ror.org/02h2x0161"
+    },
+    {
+      "label": "GSI Helmholtz Centre for Heavy Ion Research",
+      "type": "Child",
+      "id": "https://ror.org/02k8cbn47"
+    },
+    {
+      "label": "Deutsches Zentrum für Luft- und Raumfahrt e. V. (DLR)",
+      "type": "Child",
+      "id": "https://ror.org/04bwf3e34"
+    },
+    {
+      "label": "German Cancer Research Center",
+      "type": "Child",
+      "id": "https://ror.org/04cdgtt98"
+    },
+    {
+      "label": "German Center for Neurodegenerative Diseases",
+      "type": "Child",
+      "id": "https://ror.org/043j0f473"
+    },
+    {
+      "label": "Helmholtz Alberta Initiative",
+      "type": "Child",
+      "id": "https://ror.org/02yvsmh51"
+    },
+    {
+      "label": "Helmholtz Alliance for Astroparticle Physics",
+      "type": "Child",
+      "id": "https://ror.org/03wy6tp26"
+    },
+    {
+      "label": "Helmholtz Center for Information Security",
+      "type": "Child",
+      "id": "https://ror.org/02njgxr09"
+    },
+    {
+      "label": "GFZ Helmholtz Centre for Geosciences",
+      "type": "Child",
+      "id": "https://ror.org/04z8jg394"
+    },
+    {
+      "label": "Helmholtz Centre for Environmental Research",
+      "type": "Child",
+      "id": "https://ror.org/000h6jb29"
+    },
+    {
+      "label": "Helmholtz Centre for Infection Research",
+      "type": "Child",
+      "id": "https://ror.org/03d0p2685"
+    },
+    {
+      "label": "Helmholtz Graduate School for Hadron and Ion Research",
+      "type": "Child",
+      "id": "https://ror.org/01syejz95"
+    },
+    {
+      "label": "Helmholtz Zentrum München",
+      "type": "Child",
+      "id": "https://ror.org/00cfam450"
+    },
+    {
+      "label": "Helmholtz-Institute Ulm",
+      "type": "Child",
+      "id": "https://ror.org/034rhsb33"
+    },
+    {
+      "label": "Helmholtz-Zentrum Berlin für Materialien und Energie",
+      "type": "Child",
+      "id": "https://ror.org/02aj13c28"
+    },
+    {
+      "label": "Helmholtz-Zentrum Dresden-Rossendorf",
+      "type": "Child",
+      "id": "https://ror.org/01zy2cs03"
+    },
+    {
+      "label": "Helmholtz-Zentrum Hereon",
+      "type": "Child",
+      "id": "https://ror.org/03qjp1d79"
+    },
+    {
+      "label": "Karlsruhe Institute of Technology",
+      "type": "Child",
+      "id": "https://ror.org/04t3en479"
+    },
+    {
+      "label": "Max Delbrück Center",
+      "type": "Child",
+      "id": "https://ror.org/04p5ggc03"
+    },
+    {
+      "label": "Helmholtz Metadata Collaboration",
+      "type": "Child",
+      "id": "https://ror.org/04v4h0v24"
+    },
+    {
+      "label": "Brussels Office of Helmholtz Association",
+      "type": "Related",
+      "id": "https://ror.org/05sgy1v64"
+    },
+    {
+      "label": "Max Planck Institute for Plasma Physics",
+      "type": "Related",
+      "id": "https://ror.org/03taest98"
+    }
+  ],
+  "addresses": [
+    {
+      "lat": 52.52437,
+      "lng": 13.41053,
+      "state": null,
+      "state_code": null,
+      "city": "Berlin",
+      "geonames_city": {
+        "id": 2950159,
+        "city": "Berlin",
+        "geonames_admin1": {
+          "name": "Berlin",
+          "id": null,
+          "ascii_name": null,
+          "code": "DE.BE"
+        },
+        "geonames_admin2": {
+          "name": null,
+          "id": null,
+          "ascii_name": null,
+          "code": null
+        },
+        "license": {
+          "attribution": "Data from geonames.org under a CC-BY 3.0 license",
+          "license": "http://creativecommons.org/licenses/by/3.0/"
+        },
+        "nuts_level1": {
+          "name": null,
+          "code": null
+        },
+        "nuts_level2": {
+          "name": null,
+          "code": null
+        },
+        "nuts_level3": {
+          "name": null,
+          "code": null
+        }
+      },
+      "postcode": null,
+      "primary": false,
+      "line": null,
+      "country_geonames_id": null
+    }
+  ],
+  "links": ["https://www.helmholtz.de"],
+  "aliases": [],
+  "acronyms": [],
+  "wikipedia_url": "http://en.wikipedia.org/wiki/Helmholtz_Association_of_German_Research_Centres",
+  "labels": [
+    {
+      "label": "Helmholtz-Gemeinschaft Deutscher Forschungszentren",
+      "iso639": "de"
+    }
+  ],
+  "country": {
+    "country_name": "Germany",
+    "country_code": "DE"
+  },
+  "external_ids": {
+    "ISNI": {
+      "preferred": null,
+      "all": ["0000 0001 1942 5154"]
+    },
+    "FundRef": {
+      "preferred": null,
+      "all": ["501100001656", "501100009318"]
+    },
+    "Wikidata": {
+      "preferred": null,
+      "all": ["Q679913"]
+    },
+    "GRID": {
+      "preferred": "grid.211011.2",
+      "all": "grid.211011.2"
+    }
+  }
+}
diff --git a/src/app/api/__tests__/__mocks__/solrResults/23.institutionWithoutRor.json b/src/app/api/__tests__/__mocks__/solrResults/23.institutionWithoutRor.json
new file mode 100644
index 0000000..9393fb1
--- /dev/null
+++ b/src/app/api/__tests__/__mocks__/solrResults/23.institutionWithoutRor.json
@@ -0,0 +1,34 @@
+{
+  "responseHeader": {
+    "status": 0,
+    "QTime": 0,
+    "params": {
+      "q": "id:https://doi.org/10.13039/100009133",
+      "defType": "edismax",
+      "indent": "true",
+      "qf": "name^4 txt_keywords^2 text",
+      "q.op": "AND",
+      "fq": "+type:(Organization DataCatalog)",
+      "sort": "score desc, indexed_ts desc",
+      "_": "1742465259751"
+    }
+  },
+  "response": {
+    "numFound": 1,
+    "start": 0,
+    "numFoundExact": true,
+    "docs": [
+      {
+        "id": "https://doi.org/10.13039/100009133",
+        "type": "Organization",
+        "name": "Karlsruhe Institute of Technology",
+        "keys": ["id", "type", "name"],
+        "json_source": "{\"@id\": \"https://doi.org/10.13039/100009133\", \"@type\": \"Organization\", \"name\": \"Karlsruhe Institute of Technology\"}",
+        "json_uplifted": "{\"@context\": \"http://schema.org\", \"@graph\": []}",
+        "index_id": "6e7a3dcd-ca94-4f37-812b-f6070e82f045",
+        "_version_": "1826639319233724416",
+        "indexed_ts": "2025-03-15T06:10:04.091Z"
+      }
+    ]
+  }
+}
diff --git a/src/app/api/__tests__/__mocks__/solrResults/24.institutionWithRorWithoutLogo.json b/src/app/api/__tests__/__mocks__/solrResults/24.institutionWithRorWithoutLogo.json
new file mode 100644
index 0000000..14d99cc
--- /dev/null
+++ b/src/app/api/__tests__/__mocks__/solrResults/24.institutionWithRorWithoutLogo.json
@@ -0,0 +1,34 @@
+{
+  "responseHeader": {
+    "status": 0,
+    "QTime": 0,
+    "params": {
+      "q": "id:https://ror.org/04aj4c181",
+      "defType": "edismax",
+      "indent": "true",
+      "qf": "name^4 txt_keywords^2 text",
+      "q.op": "AND",
+      "fq": "+type:(Organization DataCatalog)",
+      "sort": "score desc, indexed_ts desc",
+      "_": "1742465259751"
+    }
+  },
+  "response": {
+    "numFound": 1,
+    "start": 0,
+    "numFoundExact": true,
+    "docs": [
+      {
+        "id": "https://ror.org/04aj4c181",
+        "type": "Organization",
+        "name": "Technische Informationsbibliothek (TIB)",
+        "keys": ["id", "type", "name"],
+        "json_source": "{\"@id\": \"https://ror.org/04aj4c181\", \"@type\": \"Organization\", \"name\": \"Technische Informationsbibliothek (TIB)\"}",
+        "index_id": "6d3f6fe2-1b40-4f94-b004-d67ab6bbe7b8",
+        "_version_": "1826639321038323712",
+        "indexed_ts": "2025-03-15T06:10:05.812Z",
+        "json_uplifted": "{\"@context\": \"http://schema.org\", \"@graph\": [{\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/identifier/0ceae083e574cc483921019f1352928b\", \"propertyID\": \"oai\", \"type\": \"PropertyValue\", \"value\": \"oai:zenodo.org:15020722\"}, {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/provider/4c7b20ccf49c1dbb21a45b3c8ea32def\", \"name\": \"datacite\", \"type\": \"Organization\"}, {\"affiliation\": {\"id\": \"https://ror.org/04aj4c181\"}, \"familyName\": \"Ziedorn\", \"givenName\": \"Frauke\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-1143-781X\", \"name\": \"Frauke Ziedorn\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_0/f27d47af1ffcc73b8501be896cbc6b38\", \"type\": \"Person\"}, {\"id\": \"https://ror.org/04aj4c181\", \"name\": \"Technische Informationsbibliothek (TIB)\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_0/affiliation/22ffe43dd163b5d540b5c833e6974f9f\", \"type\": \"Organization\"}, {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/publisher/d8ac2c95f46d79ce386f2aadd4053458\", \"name\": \"Zenodo\", \"type\": \"Organization\"}, {\"affiliation\": {\"id\": \"https://ror.org/02hpadn98\"}, \"familyName\": \"Czerniak\", \"givenName\": \"Andreas\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0003-3883-4169\", \"name\": \"Andreas Czerniak\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_2/c05c48ddc13fc2371c09108ca3e4d70b\", \"type\": \"Person\"}, {\"id\": \"https://ror.org/0281dp749\", \"name\": \"Helmholtz Association of German Research Centres\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_1/affiliation/2ece46936936382e0f32c95a31412dcc\", \"type\": \"Organization\"}, {\"id\": \"https://ror.org/02hpadn98\", \"name\": \"Bielefeld University\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_2/affiliation/0d75a403a14648a30be9a8cd787d1b3d\", \"type\": \"Organization\"}, {\"additionalType\": \"Presentation\", \"author\": [{\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-1143-781X\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-8912-184X\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0003-3883-4169\"}], \"datePublished\": \"2025-03-13\", \"description\": \"Persistente Identifikatoren (PIDs) spielen eine entscheidende Rolle f\\u00fcr die Entwicklung einer gemeinsamen Infrastruktur f\\u00fcr offene Wissenschaft und die Gew\\u00e4hrleistung wissenschaftlicher Integrit\\u00e4t. Sie erm\\u00f6glichen die eindeutige und dauerhafte Identifizierung von Forschungsobjekten und -daten \\u00fcber den gesamten Lebenszyklus hinweg, von der Erhebung bis zur Publikation. PIDs bieten zudem die M\\u00f6glichkeit, Forschungsprojekte, Proben, Software und Datens\\u00e4tze eindeutig zu kennzeichnen und mit Metadaten zu versehen, was zu einer vernetzten und digitalen Wissenschaftslandschaft beitr\\u00e4gt.\\n\\nDie Projekte \\\"PID Network Germany\\\" und \\\"PID4NFDI\\\" analysieren die Nutzung und Akzeptanz von PIDs in der deutschen Forschungslandschaft und haben durch gezielte Umfragen und Workshops die Bed\\u00fcrfnisse, Herausforderungen und den aktuellen Stand der Implementierung identifiziert. Insbesondere haben sie den Einfluss von PIDs auf die Sichtbarkeit und den Austausch von Forschungsergebnissen an deutschen Hochschulen und Forschungseinrichtungen untersucht.\\n\\nDer Vortrag wird die Ergebnisse dieser Untersuchungen pr\\u00e4sentieren und die Fortschritte bei der Einf\\u00fchrung von PIDs in den letzten zehn Jahren beleuchten. Er zeigt auf, wie das Projekt \\\"PID-Netzwerk Deutschland\\\" auf den Bem\\u00fchungen der erfolgreichen ORCID-DE-Projekte aufbaut, um die Verbreitung von PIDs durch Grunds\\u00e4tze wie ACTION (Advocacy, Collaboration, Training, Implementation, Outreach, Networking) voranzutreiben. Dabei werden umsetzbare Strategien vorgestellt, wie etwa die Entwicklung einer PID-Roadmap, um die Einf\\u00fchrung von PIDs in verschiedenen Bereichen zu f\\u00f6rdern und langfristig in der Forschungslandschaft zu verankern.\\n\\nAbschlie\\u00dfend werden wir einen \\u00dcberblick \\u00fcber bew\\u00e4hrte Praktiken und Zukunftsperspektiven f\\u00fcr die digitale Kuration geben, um Forschende und Institutionen bei der effektiven Implementierung von PIDs zu unterst\\u00fctzen.\", \"id\": \"https://doi.org/10.5281/zenodo.15020722\", \"identifier\": {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/identifier/0ceae083e574cc483921019f1352928b\"}, \"inLanguage\": \"de\", \"license\": \"https://creativecommons.org/licenses/by/4.0/legalcode\", \"name\": \"Die Rolle persistenter Identifikatoren (PIDs) in der offenen Wissenschaft: Status Quo und zuk\\u00fcnftige Perspektiven\", \"provider\": {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/provider/4c7b20ccf49c1dbb21a45b3c8ea32def\"}, \"publisher\": {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/publisher/d8ac2c95f46d79ce386f2aadd4053458\"}, \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/df112037e6b76b670cae8007a3fb5bc5\", \"schemaVersion\": \"http://datacite.org/schema/kernel-4\", \"type\": \"ScholarlyArticle\", \"url\": \"https://zenodo.org/doi/10.5281/zenodo.15020722\"}, {\"affiliation\": {\"id\": \"https://ror.org/0281dp749\"}, \"familyName\": \"Genderjahn\", \"givenName\": \"Steffi\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-8912-184X\", \"name\": \"Steffi Genderjahn\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_1/8a3e7a2de679aa5b2aeae59750db05d6\", \"type\": \"Person\"}]}"
+      }
+    ]
+  }
+}
diff --git a/src/app/api/__tests__/__mocks__/solrResults/25.institutionWithRorWithLogo.json b/src/app/api/__tests__/__mocks__/solrResults/25.institutionWithRorWithLogo.json
new file mode 100644
index 0000000..82bfe59
--- /dev/null
+++ b/src/app/api/__tests__/__mocks__/solrResults/25.institutionWithRorWithLogo.json
@@ -0,0 +1,34 @@
+{
+  "responseHeader": {
+    "status": 0,
+    "QTime": 0,
+    "params": {
+      "q": "id:https://ror.org/0281dp749",
+      "defType": "edismax",
+      "indent": "true",
+      "qf": "name^4 txt_keywords^2 text",
+      "q.op": "AND",
+      "fq": "+type:(Organization DataCatalog)",
+      "sort": "score desc, indexed_ts desc",
+      "_": "1742465259751"
+    }
+  },
+  "response": {
+    "numFound": 1,
+    "start": 0,
+    "numFoundExact": true,
+    "docs": [
+      {
+        "id": "https://ror.org/0281dp749",
+        "type": "Organization",
+        "name": "Helmholtz Association of German Research Centres",
+        "keys": ["id", "type", "name"],
+        "json_source": "{\"@id\": \"https://ror.org/0281dp749\", \"@type\": \"Organization\", \"name\": \"Helmholtz Association of German Research Centres\"}",
+        "index_id": "2fa91c2c-bd27-48f5-a0c6-14da9494622d",
+        "_version_": "1826639321205047296",
+        "indexed_ts": "2025-03-15T06:10:05.971Z",
+        "json_uplifted": "{\"@context\": \"http://schema.org\", \"@graph\": [{\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/identifier/0ceae083e574cc483921019f1352928b\", \"propertyID\": \"oai\", \"type\": \"PropertyValue\", \"value\": \"oai:zenodo.org:15020722\"}, {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/provider/4c7b20ccf49c1dbb21a45b3c8ea32def\", \"name\": \"datacite\", \"type\": \"Organization\"}, {\"affiliation\": {\"id\": \"https://ror.org/04aj4c181\"}, \"familyName\": \"Ziedorn\", \"givenName\": \"Frauke\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-1143-781X\", \"name\": \"Frauke Ziedorn\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_0/f27d47af1ffcc73b8501be896cbc6b38\", \"type\": \"Person\"}, {\"id\": \"https://ror.org/04aj4c181\", \"name\": \"Technische Informationsbibliothek (TIB)\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_0/affiliation/22ffe43dd163b5d540b5c833e6974f9f\", \"type\": \"Organization\"}, {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/publisher/d8ac2c95f46d79ce386f2aadd4053458\", \"name\": \"Zenodo\", \"type\": \"Organization\"}, {\"affiliation\": {\"id\": \"https://ror.org/02hpadn98\"}, \"familyName\": \"Czerniak\", \"givenName\": \"Andreas\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0003-3883-4169\", \"name\": \"Andreas Czerniak\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_2/c05c48ddc13fc2371c09108ca3e4d70b\", \"type\": \"Person\"}, {\"id\": \"https://ror.org/0281dp749\", \"name\": \"Helmholtz Association of German Research Centres\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_1/affiliation/2ece46936936382e0f32c95a31412dcc\", \"type\": \"Organization\"}, {\"id\": \"https://ror.org/02hpadn98\", \"name\": \"Bielefeld University\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_2/affiliation/0d75a403a14648a30be9a8cd787d1b3d\", \"type\": \"Organization\"}, {\"additionalType\": \"Presentation\", \"author\": [{\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-1143-781X\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-8912-184X\"}, {\"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0003-3883-4169\"}], \"datePublished\": \"2025-03-13\", \"description\": \"Persistente Identifikatoren (PIDs) spielen eine entscheidende Rolle f\\u00fcr die Entwicklung einer gemeinsamen Infrastruktur f\\u00fcr offene Wissenschaft und die Gew\\u00e4hrleistung wissenschaftlicher Integrit\\u00e4t. Sie erm\\u00f6glichen die eindeutige und dauerhafte Identifizierung von Forschungsobjekten und -daten \\u00fcber den gesamten Lebenszyklus hinweg, von der Erhebung bis zur Publikation. PIDs bieten zudem die M\\u00f6glichkeit, Forschungsprojekte, Proben, Software und Datens\\u00e4tze eindeutig zu kennzeichnen und mit Metadaten zu versehen, was zu einer vernetzten und digitalen Wissenschaftslandschaft beitr\\u00e4gt.\\n\\nDie Projekte \\\"PID Network Germany\\\" und \\\"PID4NFDI\\\" analysieren die Nutzung und Akzeptanz von PIDs in der deutschen Forschungslandschaft und haben durch gezielte Umfragen und Workshops die Bed\\u00fcrfnisse, Herausforderungen und den aktuellen Stand der Implementierung identifiziert. Insbesondere haben sie den Einfluss von PIDs auf die Sichtbarkeit und den Austausch von Forschungsergebnissen an deutschen Hochschulen und Forschungseinrichtungen untersucht.\\n\\nDer Vortrag wird die Ergebnisse dieser Untersuchungen pr\\u00e4sentieren und die Fortschritte bei der Einf\\u00fchrung von PIDs in den letzten zehn Jahren beleuchten. Er zeigt auf, wie das Projekt \\\"PID-Netzwerk Deutschland\\\" auf den Bem\\u00fchungen der erfolgreichen ORCID-DE-Projekte aufbaut, um die Verbreitung von PIDs durch Grunds\\u00e4tze wie ACTION (Advocacy, Collaboration, Training, Implementation, Outreach, Networking) voranzutreiben. Dabei werden umsetzbare Strategien vorgestellt, wie etwa die Entwicklung einer PID-Roadmap, um die Einf\\u00fchrung von PIDs in verschiedenen Bereichen zu f\\u00f6rdern und langfristig in der Forschungslandschaft zu verankern.\\n\\nAbschlie\\u00dfend werden wir einen \\u00dcberblick \\u00fcber bew\\u00e4hrte Praktiken und Zukunftsperspektiven f\\u00fcr die digitale Kuration geben, um Forschende und Institutionen bei der effektiven Implementierung von PIDs zu unterst\\u00fctzen.\", \"id\": \"https://doi.org/10.5281/zenodo.15020722\", \"identifier\": {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/identifier/0ceae083e574cc483921019f1352928b\"}, \"inLanguage\": \"de\", \"license\": \"https://creativecommons.org/licenses/by/4.0/legalcode\", \"name\": \"Die Rolle persistenter Identifikatoren (PIDs) in der offenen Wissenschaft: Status Quo und zuk\\u00fcnftige Perspektiven\", \"provider\": {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/provider/4c7b20ccf49c1dbb21a45b3c8ea32def\"}, \"publisher\": {\"id\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/publisher/d8ac2c95f46d79ce386f2aadd4053458\"}, \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/df112037e6b76b670cae8007a3fb5bc5\", \"schemaVersion\": \"http://datacite.org/schema/kernel-4\", \"type\": \"ScholarlyArticle\", \"url\": \"https://zenodo.org/doi/10.5281/zenodo.15020722\"}, {\"affiliation\": {\"id\": \"https://ror.org/0281dp749\"}, \"familyName\": \"Genderjahn\", \"givenName\": \"Steffi\", \"id\": \"file:///tmp/tmpxbd0demyprefect/0000-0002-8912-184X\", \"name\": \"Steffi Genderjahn\", \"sameAs\": \"https://helmholtz-metadaten.de/.well-known/genid/f2e192df3a4f1/author_1/8a3e7a2de679aa5b2aeae59750db05d6\", \"type\": \"Person\"}]}"
+      }
+    ]
+  }
+}
diff --git a/src/app/api/__tests__/api/details.test.ts b/src/app/api/__tests__/api/details.test.ts
index 3bd614b..11ef562 100644
--- a/src/app/api/__tests__/api/details.test.ts
+++ b/src/app/api/__tests__/api/details.test.ts
@@ -1,10 +1,13 @@
 import { NextRequest } from "next/server";
 
-import solrDatasetResponse from "@api/__tests__/__mocks__/solrResults/13.datasetSource.json";
+import rorWithoutLogo from "@api/__tests__/__mocks__/rorResults/24.rorWithoutLogo.json";
+import rorWithLogo from "@api/__tests__/__mocks__/rorResults/25.rorWithLogo.json";
 import solrMisformedIdCorrectDocType from "@api/__tests__/__mocks__/solrResults/20.misformedIdCorrectDocType.json";
 import solrCorrectIdMismatchedDocType from "@api/__tests__/__mocks__/solrResults/21.correctIdMismatchedDocType.json";
 import solrSoftwareDetails from "@api/__tests__/__mocks__/solrResults/22.softwareDetails.json";
-import datasetSource from "@api/__tests__/expectedApiResults/13.datasetSource.json";
+import solrInstitutionWithoutRor from "@api/__tests__/__mocks__/solrResults/23.institutionWithoutRor.json";
+import solrInstitutionWithRorWithoutLogo from "@api/__tests__/__mocks__/solrResults/24.institutionWithRorWithoutLogo.json";
+import solrInstitutionWithRorWithLogo from "@api/__tests__/__mocks__/solrResults/25.institutionWithRorWithLogo.json";
 import missingId from "@api/__tests__/expectedApiResults/15.missingId.json";
 import missingDocumentType from "@api/__tests__/expectedApiResults/16.missingDocumentType.json";
 import missingParams from "@api/__tests__/expectedApiResults/17.missingParams.json";
@@ -13,6 +16,9 @@ import emptyStringId from "@api/__tests__/expectedApiResults/19.emptyStringId.js
 import misformedIdCorrectDocType from "@api/__tests__/expectedApiResults/20.misformedIdCorrectDocType.json";
 import correctIdMismatchedDocType from "@api/__tests__/expectedApiResults/21.correctIdMismatchedDocType.json";
 import softwareDetails from "@api/__tests__/expectedApiResults/22.softwareDetails.json";
+import institutionWithoutRor from "@api/__tests__/expectedApiResults/23.institutionWithoutRor.json";
+import institutionWithRorWithoutLogo from "@api/__tests__/expectedApiResults/24.institutionWithRorWithoutLogo.json";
+import institutionWithRorWithLogo from "@api/__tests__/expectedApiResults/25.institutionWithRorWithLogo.json";
 import { GET } from "@api/details/route";
 
 describe("unit tests for /details API Endpoint", () => {
@@ -103,7 +109,7 @@ describe("unit tests for /details API Endpoint", () => {
     expect(jsonResult).toMatchObject(correctIdMismatchedDocType);
   });
 
-  it.skip("22.should return result item for given documentType and ID", async () => {
+  it("22.should return result item for given documentType and ID", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
         json: () => Promise.resolve(solrSoftwareDetails),
@@ -119,10 +125,10 @@ describe("unit tests for /details API Endpoint", () => {
     expect(jsonResult).toMatchObject(softwareDetails);
   });
 
-  it.skip("23.should return result item for the institute with given ID, without any ROR enrichment", async () => {
+  it("23.should return result item for the institute with given ID, without any ROR enrichment", async () => {
     jest.spyOn(global, "fetch").mockImplementationOnce(() =>
       Promise.resolve({
-        json: () => Promise.resolve(solrDatasetResponse),
+        json: () => Promise.resolve(solrInstitutionWithoutRor),
       } as Response)
     );
 
@@ -133,15 +139,20 @@ describe("unit tests for /details API Endpoint", () => {
     const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(200);
-    expect(jsonResult).toMatchObject(datasetSource);
+    expect(jsonResult).toMatchObject(institutionWithoutRor);
   });
 
-  it.skip("24.should return result item for the institute with given ID,with ROR enrichment but without any information about logos", async () => {
-    jest.spyOn(global, "fetch").mockImplementationOnce(() =>
-      Promise.resolve({
-        json: () => Promise.resolve(solrDatasetResponse),
-      } as Response)
-    );
+  it("24.should return result item for the institute with given ID,with ROR enrichment but without any information about logos", async () => {
+    jest
+      .spyOn(global, "fetch")
+      .mockImplementationOnce(() =>
+        Promise.resolve({
+          json: () => Promise.resolve(solrInstitutionWithRorWithoutLogo),
+        } as Response)
+      )
+      .mockImplementationOnce(() =>
+        Promise.resolve({ json: () => Promise.resolve(rorWithoutLogo) } as Response)
+      );
 
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://ror.org/04aj4c181");
@@ -150,15 +161,20 @@ describe("unit tests for /details API Endpoint", () => {
     const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(200);
-    expect(jsonResult).toMatchObject(datasetSource);
+    expect(jsonResult).toMatchObject(institutionWithRorWithoutLogo);
   });
 
-  it.skip("25.should return result item for the institute with given ID,with ROR enrichment but with information on logos", async () => {
-    jest.spyOn(global, "fetch").mockImplementationOnce(() =>
-      Promise.resolve({
-        json: () => Promise.resolve(solrDatasetResponse),
-      } as Response)
-    );
+  it("25.should return result item for the institute with given ID,with ROR enrichment but with information on logos", async () => {
+    jest
+      .spyOn(global, "fetch")
+      .mockImplementationOnce(() =>
+        Promise.resolve({
+          json: () => Promise.resolve(solrInstitutionWithRorWithLogo),
+        } as Response)
+      )
+      .mockImplementationOnce(() =>
+        Promise.resolve({ json: () => Promise.resolve(rorWithLogo) } as Response)
+      );
 
     const req = new NextRequest(new Request("https://www.whatever.com"), {});
     req.nextUrl.searchParams.append("id", "https://ror.org/0281dp749");
@@ -167,6 +183,6 @@ describe("unit tests for /details API Endpoint", () => {
     const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
     expect(response.status).toBe(200);
-    expect(jsonResult).toMatchObject(datasetSource);
+    expect(jsonResult).toMatchObject(institutionWithRorWithLogo);
   });
 });
diff --git a/src/app/api/__tests__/expectedApiResults/22.softwareDetails.json b/src/app/api/__tests__/expectedApiResults/22.softwareDetails.json
index 62e4399..9932c7f 100644
--- a/src/app/api/__tests__/expectedApiResults/22.softwareDetails.json
+++ b/src/app/api/__tests__/expectedApiResults/22.softwareDetails.json
@@ -9,7 +9,7 @@
     "Nikolay V. Koldunov",
     "Thomas Jung"
   ],
-  "description": "ClimSight is an advanced tool that integrates Large Language Models (LLMs) with climate data to provide localized climate insights for decision-making. ClimSight transforms complex climate data into actionable insights for agriculture, urban planning, disaster management, and policy development.\n\n      The target audience includes researchers, providers of climate services, policymakers, agricultural planners, urban developers, and other stakeholders who require detailed climate information to support decision-making. ClimSight is designed to democratize access to climate data, empowering users with insights relevant to their specific contexts.\n\n      ClimSight distinguishes itself through several key advancements:\n\n      Integration of LLMs: ClimSight leverages state-of-the-art LLMs to interpret complex climate-related queries, synthesizing information from diverse data sources.\n\n      Multi-Source Data Integration: Unlike conventional systems that rely solely on structured climate data, ClimSight integrates information from multiple sources.\n\n      Evidence-Based Approach: ClimSight ensures contextually accurate answers by retrieving relevant knowledge from scientific reports, IPCC documents, and geographical databases.\n\n      Modular Architecture: Specialized components handle distinct tasks, such as data retrieval, contextual understanding, and result synthesis, leading to more accurate outputs.\n\n      Real-World Applications: ClimSight is validated through practical examples, such as assessing climate risks for specific agricultural activities and urban planning scenarios.\n\n      AcknowledgementsThis work was supported by the European Union's Destination Earth Initiative and relates to tasks entrusted by the European Union to the European Centre for Medium-Range Weather Forecasts, implementing part of this Initiative with funding by the European Union. We also thank the Helmholtz Association and the Federal Ministry of Education and Research (BMBF) for supporting the DataHub Initiative of the Research Field Earth and Environment, which contributed to this study. Additionally, this work is supported by project S1: Diagnosis and Metrics in Climate Models of the Collaborative Research Centre TRR 181 .Energy Transfer in Atmosphere and Ocean, funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation, project no. 274762653). Views and opinions expressed are those of the authors only and do not necessarily reflect those of the European Union or the European Climate Infrastructure and Environment Executive Agency (CINEA). Neither the European Union nor the granting authority can be held responsible for them.",
+  "description": "ClimSight is an advanced tool that integrates Large Language Models (LLMs) with climate data to provide localized climate insights for decision-making. ClimSight transforms complex climate data into actionable insights for agriculture, urban planning, disaster management, and policy development.\n\nThe target audience includes researchers, providers of climate services, policymakers, agricultural planners, urban developers, and other stakeholders who require detailed climate information to support decision-making. ClimSight is designed to democratize access to climate data, empowering users with insights relevant to their specific contexts.\n\nClimSight distinguishes itself through several key advancements:\n\n\n\nIntegration of LLMs: ClimSight leverages state-of-the-art LLMs to interpret complex climate-related queries, synthesizing information from diverse data sources.\n\nMulti-Source Data Integration: Unlike conventional systems that rely solely on structured climate data, ClimSight integrates information from multiple sources.\n\nEvidence-Based Approach: ClimSight ensures contextually accurate answers by retrieving relevant knowledge from scientific reports, IPCC documents, and geographical databases.\n\nModular Architecture: Specialized components handle distinct tasks, such as data retrieval, contextual understanding, and result synthesis, leading to more accurate outputs.\n\nReal-World Applications: ClimSight is validated through practical examples, such as assessing climate risks for specific agricultural activities and urban planning scenarios.\n\n\nAcknowledgementsThis work was supported by the European Union’s Destination Earth Initiative and relates to tasks entrusted by the European Union to the European Centre for Medium-Range Weather Forecasts, implementing part of this Initiative with funding by the European Union. We also thank the Helmholtz Association and the Federal Ministry of Education and Research (BMBF) for supporting the DataHub Initiative of the Research Field Earth and Environment, which contributed to this study. Additionally, this work is supported by project S1: Diagnosis and Metrics in Climate Models of the Collaborative Research Centre TRR 181 “Energy Transfer in Atmosphere and Ocean,” funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation, project no. 274762653). Views and opinions expressed are those of the authors only and do not necessarily reflect those of the European Union or the European Climate Infrastructure and Environment Executive Agency (CINEA). Neither the European Union nor the granting authority can be held responsible for them.",
   "name": "ClimSight: Transforming Climate Services with LLMs and Multi-Source Data Integration",
   "txt_provider": ["datacite"],
   "txt_publisher": ["Zenodo"],
diff --git a/src/app/api/__tests__/expectedApiResults/23.institutionWithoutRor.json b/src/app/api/__tests__/expectedApiResults/23.institutionWithoutRor.json
new file mode 100644
index 0000000..6a8db97
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/23.institutionWithoutRor.json
@@ -0,0 +1,11 @@
+{
+  "id": "https://doi.org/10.13039/100009133",
+  "type": "Organization",
+  "name": "Karlsruhe Institute of Technology",
+  "keys": ["id", "type", "name"],
+  "recordConfig": {
+    "index_id": "6e7a3dcd-ca94-4f37-812b-f6070e82f045",
+    "_version_": "1826639319233724416",
+    "indexed_ts": "2025-03-15T06:10:04.091Z"
+  }
+}
diff --git a/src/app/api/__tests__/expectedApiResults/24.institutionWithRorWithoutLogo.json b/src/app/api/__tests__/expectedApiResults/24.institutionWithRorWithoutLogo.json
new file mode 100644
index 0000000..9482c6c
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/24.institutionWithRorWithoutLogo.json
@@ -0,0 +1,105 @@
+{
+  "id": "https://ror.org/04aj4c181",
+  "type": "Organization",
+  "name": "Technische Informationsbibliothek (TIB)",
+  "keys": ["id", "type", "name"],
+  "recordConfig": {
+    "index_id": "6d3f6fe2-1b40-4f94-b004-d67ab6bbe7b8",
+    "_version_": "1826639321038323712",
+    "indexed_ts": "2025-03-15T06:10:05.812Z"
+  },
+  "status": "active",
+  "email_address": null,
+  "ip_addresses": [],
+  "established": 1959,
+  "types": ["Archive"],
+  "relationships": [
+    {
+      "label": "Leibniz Association",
+      "type": "Parent",
+      "id": "https://ror.org/01n6r0e97"
+    },
+    {
+      "label": "TIB Open Publishing",
+      "type": "Child",
+      "id": "https://ror.org/058nncw69"
+    }
+  ],
+  "addresses": [
+    {
+      "lat": 52.37052,
+      "lng": 9.73322,
+      "state": null,
+      "state_code": null,
+      "city": "Hanover",
+      "geonames_city": {
+        "id": 2910831,
+        "city": "Hanover",
+        "geonames_admin1": {
+          "name": "Lower Saxony",
+          "id": null,
+          "ascii_name": null,
+          "code": "DE.NI"
+        },
+        "geonames_admin2": {
+          "name": null,
+          "id": null,
+          "ascii_name": null,
+          "code": null
+        },
+        "license": {
+          "attribution": "Data from geonames.org under a CC-BY 3.0 license",
+          "license": "http://creativecommons.org/licenses/by/3.0/"
+        },
+        "nuts_level1": {
+          "name": null,
+          "code": null
+        },
+        "nuts_level2": {
+          "name": null,
+          "code": null
+        },
+        "nuts_level3": {
+          "name": null,
+          "code": null
+        }
+      },
+      "postcode": null,
+      "primary": false,
+      "line": null,
+      "country_geonames_id": null
+    }
+  ],
+  "links": ["https://www.tib.eu/en/"],
+  "aliases": [
+    "German National Library of Science and Technology",
+    "German National Library of Science and Technology (TIB) - Leibniz Information Centre for Science and Technology - University Library",
+    "Technische Informationsbibliothek (TIB) - Leibniz-Informationszentrum Technik und Naturwissenschaften - Universitätsbibliothek"
+  ],
+  "acronyms": ["TIB"],
+  "wikipedia_url": "https://en.wikipedia.org/wiki/German_National_Library_of_Science_and_Technology",
+  "labels": [
+    {
+      "label": "Technische Informationsbibliothek",
+      "iso639": "de"
+    }
+  ],
+  "country": {
+    "country_name": "Germany",
+    "country_code": "DE"
+  },
+  "external_ids": {
+    "ISNI": {
+      "preferred": null,
+      "all": ["0000 0001 2174 6694"]
+    },
+    "Wikidata": {
+      "preferred": null,
+      "all": ["Q2399120"]
+    },
+    "GRID": {
+      "preferred": "grid.461819.3",
+      "all": "grid.461819.3"
+    }
+  }
+}
diff --git a/src/app/api/__tests__/expectedApiResults/25.institutionWithRorWithLogo.json b/src/app/api/__tests__/expectedApiResults/25.institutionWithRorWithLogo.json
new file mode 100644
index 0000000..babe2e8
--- /dev/null
+++ b/src/app/api/__tests__/expectedApiResults/25.institutionWithRorWithLogo.json
@@ -0,0 +1,222 @@
+{
+  "id": "https://ror.org/0281dp749",
+  "type": "Organization",
+  "name": "Helmholtz Association of German Research Centres",
+  "keys": ["id", "type", "name"],
+  "recordConfig": {
+    "index_id": "2fa91c2c-bd27-48f5-a0c6-14da9494622d",
+    "_version_": "1826639321205047296",
+    "indexed_ts": "2025-03-15T06:10:05.971Z"
+  },
+  "status": "active",
+  "email_address": null,
+  "ip_addresses": [],
+  "established": 1995,
+  "types": ["Funder", "Government"],
+  "relationships": [
+    {
+      "label": "Alfred-Wegener-Institut Helmholtz-Zentrum für Polar- und Meeresforschung",
+      "type": "Child",
+      "id": "https://ror.org/032e6b942"
+    },
+    {
+      "label": "Deutsches Elektronen-Synchrotron DESY",
+      "type": "Child",
+      "id": "https://ror.org/01js2sh04"
+    },
+    {
+      "label": "Forschungszentrum Jülich",
+      "type": "Child",
+      "id": "https://ror.org/02nv7yv05"
+    },
+    {
+      "label": "GEOMAR Helmholtz Centre for Ocean Research Kiel",
+      "type": "Child",
+      "id": "https://ror.org/02h2x0161"
+    },
+    {
+      "label": "GSI Helmholtz Centre for Heavy Ion Research",
+      "type": "Child",
+      "id": "https://ror.org/02k8cbn47"
+    },
+    {
+      "label": "Deutsches Zentrum für Luft- und Raumfahrt e. V. (DLR)",
+      "type": "Child",
+      "id": "https://ror.org/04bwf3e34"
+    },
+    {
+      "label": "German Cancer Research Center",
+      "type": "Child",
+      "id": "https://ror.org/04cdgtt98"
+    },
+    {
+      "label": "German Center for Neurodegenerative Diseases",
+      "type": "Child",
+      "id": "https://ror.org/043j0f473"
+    },
+    {
+      "label": "Helmholtz Alberta Initiative",
+      "type": "Child",
+      "id": "https://ror.org/02yvsmh51"
+    },
+    {
+      "label": "Helmholtz Alliance for Astroparticle Physics",
+      "type": "Child",
+      "id": "https://ror.org/03wy6tp26"
+    },
+    {
+      "label": "Helmholtz Center for Information Security",
+      "type": "Child",
+      "id": "https://ror.org/02njgxr09"
+    },
+    {
+      "label": "GFZ Helmholtz Centre for Geosciences",
+      "type": "Child",
+      "id": "https://ror.org/04z8jg394"
+    },
+    {
+      "label": "Helmholtz Centre for Environmental Research",
+      "type": "Child",
+      "id": "https://ror.org/000h6jb29"
+    },
+    {
+      "label": "Helmholtz Centre for Infection Research",
+      "type": "Child",
+      "id": "https://ror.org/03d0p2685"
+    },
+    {
+      "label": "Helmholtz Graduate School for Hadron and Ion Research",
+      "type": "Child",
+      "id": "https://ror.org/01syejz95"
+    },
+    {
+      "label": "Helmholtz Zentrum München",
+      "type": "Child",
+      "id": "https://ror.org/00cfam450"
+    },
+    {
+      "label": "Helmholtz-Institute Ulm",
+      "type": "Child",
+      "id": "https://ror.org/034rhsb33"
+    },
+    {
+      "label": "Helmholtz-Zentrum Berlin für Materialien und Energie",
+      "type": "Child",
+      "id": "https://ror.org/02aj13c28"
+    },
+    {
+      "label": "Helmholtz-Zentrum Dresden-Rossendorf",
+      "type": "Child",
+      "id": "https://ror.org/01zy2cs03"
+    },
+    {
+      "label": "Helmholtz-Zentrum Hereon",
+      "type": "Child",
+      "id": "https://ror.org/03qjp1d79"
+    },
+    {
+      "label": "Karlsruhe Institute of Technology",
+      "type": "Child",
+      "id": "https://ror.org/04t3en479"
+    },
+    {
+      "label": "Max Delbrück Center",
+      "type": "Child",
+      "id": "https://ror.org/04p5ggc03"
+    },
+    {
+      "label": "Helmholtz Metadata Collaboration",
+      "type": "Child",
+      "id": "https://ror.org/04v4h0v24"
+    },
+    {
+      "label": "Brussels Office of Helmholtz Association",
+      "type": "Related",
+      "id": "https://ror.org/05sgy1v64"
+    },
+    {
+      "label": "Max Planck Institute for Plasma Physics",
+      "type": "Related",
+      "id": "https://ror.org/03taest98"
+    }
+  ],
+  "addresses": [
+    {
+      "lat": 52.52437,
+      "lng": 13.41053,
+      "state": null,
+      "state_code": null,
+      "city": "Berlin",
+      "geonames_city": {
+        "id": 2950159,
+        "city": "Berlin",
+        "geonames_admin1": {
+          "name": "Berlin",
+          "id": null,
+          "ascii_name": null,
+          "code": "DE.BE"
+        },
+        "geonames_admin2": {
+          "name": null,
+          "id": null,
+          "ascii_name": null,
+          "code": null
+        },
+        "license": {
+          "attribution": "Data from geonames.org under a CC-BY 3.0 license",
+          "license": "http://creativecommons.org/licenses/by/3.0/"
+        },
+        "nuts_level1": {
+          "name": null,
+          "code": null
+        },
+        "nuts_level2": {
+          "name": null,
+          "code": null
+        },
+        "nuts_level3": {
+          "name": null,
+          "code": null
+        }
+      },
+      "postcode": null,
+      "primary": false,
+      "line": null,
+      "country_geonames_id": null
+    }
+  ],
+  "links": ["https://www.helmholtz.de"],
+  "aliases": [],
+  "acronyms": [],
+  "wikipedia_url": "http://en.wikipedia.org/wiki/Helmholtz_Association_of_German_Research_Centres",
+  "labels": [
+    {
+      "label": "Helmholtz-Gemeinschaft Deutscher Forschungszentren",
+      "iso639": "de"
+    }
+  ],
+  "country": {
+    "country_name": "Germany",
+    "country_code": "DE"
+  },
+  "external_ids": {
+    "ISNI": {
+      "preferred": null,
+      "all": ["0000 0001 1942 5154"]
+    },
+    "FundRef": {
+      "preferred": null,
+      "all": ["501100001656", "501100009318"]
+    },
+    "Wikidata": {
+      "preferred": null,
+      "all": ["Q679913"]
+    },
+    "GRID": {
+      "preferred": "grid.211011.2",
+      "all": "grid.211011.2"
+    }
+  },
+  "logo": "https://upload.wikimedia.org/wikipedia/commons/9/94/Helmholtz_Association%27s_Logo.svg",
+  "favicon": "https://www.helmholtz.de/typo3conf/ext/dreipc_hgf/Resources/Public/Frontend/Build/assets/icons/favicons/icon-228x228.png"
+}
diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index db0ec92..82bb130 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -7,15 +7,38 @@ import {
   SolrResponseDocsType,
   SolrResponseType,
 } from "@/types/types";
-import { SOLR_QUERY_DEFAULTS } from "@api/config/config";
+import { SOLR_QUERY_DEFAULTS, INSTITUTE_ROR_LOGOS } from "@api/config/config";
 import {
   createFacetParams,
   createResultItem,
   createSearchParamsMap,
   handleDetailsParamErrors,
 } from "@api/utils/shared";
+import SolrQuery from "@api/utils/solrQuery";
 
-import SolrQuery from "../utils/solrQuery";
+const getEnrichedRecords = async (rorRecords: ResultItem[]): Promise<ResultItem[]> => {
+  const withEnrichedRecords: ResultItem[] = [];
+  for (const record of rorRecords) {
+    const rorId = record.id.startsWith("https://ror.org") ? record.id.split("/").pop() : null;
+
+    try {
+      if (rorId) {
+        const rorInfo = await fetch(`https://api.ror.org/organizations/${rorId}`, {
+          headers: {
+            Accept: "application/json",
+          },
+        });
+        withEnrichedRecords.push({ ...record, ...(await rorInfo.json()) });
+      } else {
+        withEnrichedRecords.push(record);
+      }
+    } catch (error) {
+      console.error("Error while enriching record:", error);
+      withEnrichedRecords.push(record);
+    }
+  }
+  return withEnrichedRecords;
+};
 
 export const GET = async (req: NextRequest) => {
   try {
@@ -51,12 +74,27 @@ export const GET = async (req: NextRequest) => {
       const solrResponseRecord: ResultItem[] = solrResponse.response.docs.map(
         (record: SolrResponseDocsType) => createResultItem(record)
       );
-      console.log(solrResponseRecord[0]);
+      const solrResultItem = solrResponseRecord[0];
+
       if (documentType === "institutions") {
-        // TODO: add ROR enrichment & logo enrichment
-        return Response.json(solrResponseRecord[0], { status: 200 });
+        if (solrResultItem.id.startsWith("https://ror.org")) {
+          const enrichedRecords = await getEnrichedRecords(solrResponseRecord);
+          const logoItem = INSTITUTE_ROR_LOGOS.filter(
+            (item) => item.id === enrichedRecords[0].id
+          )[0];
+          if (logoItem) {
+            return Response.json(
+              { ...enrichedRecords[0], logo: logoItem.logo, favicon: logoItem.favicon },
+              { status: 200 }
+            );
+          } else {
+            return Response.json(enrichedRecords[0], { status: 200 });
+          }
+        } else {
+          return Response.json(solrResultItem, { status: 200 });
+        }
       } else {
-        return Response.json(solrResponseRecord[0], { status: 200 });
+        return Response.json(solrResultItem, { status: 200 });
       }
     }
   } catch (error) {
diff --git a/src/types/types.ts b/src/types/types.ts
index c4634a7..24c3f93 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -137,7 +137,12 @@ export type RorResultItem = {
   wikipedia_url?: string;
 };
 
-export type ResultItem = ResultDocs & ResultConfig & ResultKeys & RorResultItem;
+type institutionLogos = {
+  logo: string;
+  favicon: string;
+};
+
+export type ResultItem = ResultDocs & ResultConfig & ResultKeys & RorResultItem & institutionLogos;
 
 // useless for now, later if we type the entities this will help
 export type FilterProps = string;
-- 
GitLab


From 2ac21f80cbc88f00af0220856830f98e9605706e Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 20 Mar 2025 12:38:26 +0100
Subject: [PATCH 46/55] moved ror api call function to shared items, made logo
 information optional on resultItem and simplified code structure in the api

---
 src/app/api/details/route.ts | 60 ++++++++++--------------------------
 src/app/api/utils/shared.ts  | 24 +++++++++++++++
 src/types/types.ts           |  4 +--
 3 files changed, 42 insertions(+), 46 deletions(-)

diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 82bb130..f046419 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -13,33 +13,10 @@ import {
   createResultItem,
   createSearchParamsMap,
   handleDetailsParamErrors,
+  getEnrichedRecords,
 } from "@api/utils/shared";
 import SolrQuery from "@api/utils/solrQuery";
 
-const getEnrichedRecords = async (rorRecords: ResultItem[]): Promise<ResultItem[]> => {
-  const withEnrichedRecords: ResultItem[] = [];
-  for (const record of rorRecords) {
-    const rorId = record.id.startsWith("https://ror.org") ? record.id.split("/").pop() : null;
-
-    try {
-      if (rorId) {
-        const rorInfo = await fetch(`https://api.ror.org/organizations/${rorId}`, {
-          headers: {
-            Accept: "application/json",
-          },
-        });
-        withEnrichedRecords.push({ ...record, ...(await rorInfo.json()) });
-      } else {
-        withEnrichedRecords.push(record);
-      }
-    } catch (error) {
-      console.error("Error while enriching record:", error);
-      withEnrichedRecords.push(record);
-    }
-  }
-  return withEnrichedRecords;
-};
-
 export const GET = async (req: NextRequest) => {
   try {
     const detailsParamsMap = createSearchParamsMap(req.nextUrl.searchParams);
@@ -65,7 +42,7 @@ export const GET = async (req: NextRequest) => {
       documentType
     ).json();
 
-    if (solrResponse?.response?.numFound === 0) {
+    if (solrResponse.response.numFound === 0) {
       return Response.json(
         { error: { message: "No results found for given ID and documentType" } },
         { status: 400 }
@@ -76,26 +53,21 @@ export const GET = async (req: NextRequest) => {
       );
       const solrResultItem = solrResponseRecord[0];
 
-      if (documentType === "institutions") {
-        if (solrResultItem.id.startsWith("https://ror.org")) {
-          const enrichedRecords = await getEnrichedRecords(solrResponseRecord);
-          const logoItem = INSTITUTE_ROR_LOGOS.filter(
-            (item) => item.id === enrichedRecords[0].id
-          )[0];
-          if (logoItem) {
-            return Response.json(
-              { ...enrichedRecords[0], logo: logoItem.logo, favicon: logoItem.favicon },
-              { status: 200 }
-            );
-          } else {
-            return Response.json(enrichedRecords[0], { status: 200 });
-          }
-        } else {
-          return Response.json(solrResultItem, { status: 200 });
-        }
-      } else {
-        return Response.json(solrResultItem, { status: 200 });
+      if (documentType === "institutions" && solrResultItem.id.startsWith("https://ror.org")) {
+        const enrichedRecords = await getEnrichedRecords(solrResponseRecord);
+        const enrichedRecord = enrichedRecords[0];
+        const logoItem = INSTITUTE_ROR_LOGOS.find((item) => item.id === enrichedRecord.id);
+
+        return Response.json(
+          {
+            ...enrichedRecord,
+            ...(logoItem && { logo: logoItem.logo, favicon: logoItem.favicon }),
+          },
+          { status: 200 }
+        );
       }
+
+      return Response.json(solrResultItem, { status: 200 });
     }
   } catch (error) {
     console.error("Error while handling details", error);
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index 1a68e55..5a2d2a1 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -206,3 +206,27 @@ export const handleDetailsParamErrors = (errors: ZodIssue[]) => {
     return errorResponse(`Request missing ${missingParams} parameters`);
   }
 };
+
+export const getEnrichedRecords = async (rorRecords: ResultItem[]): Promise<ResultItem[]> => {
+  const withEnrichedRecords: ResultItem[] = [];
+  for (const record of rorRecords) {
+    const rorId = record.id.startsWith("https://ror.org") ? record.id.split("/").pop() : null;
+
+    try {
+      if (rorId) {
+        const rorInfo = await fetch(`https://api.ror.org/organizations/${rorId}`, {
+          headers: {
+            Accept: "application/json",
+          },
+        });
+        withEnrichedRecords.push({ ...record, ...(await rorInfo.json()) });
+      } else {
+        withEnrichedRecords.push(record);
+      }
+    } catch (error) {
+      console.error("Error while enriching record:", error);
+      withEnrichedRecords.push(record);
+    }
+  }
+  return withEnrichedRecords;
+};
diff --git a/src/types/types.ts b/src/types/types.ts
index 24c3f93..fb852ae 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -138,8 +138,8 @@ export type RorResultItem = {
 };
 
 type institutionLogos = {
-  logo: string;
-  favicon: string;
+  logo?: string;
+  favicon?: string;
 };
 
 export type ResultItem = ResultDocs & ResultConfig & ResultKeys & RorResultItem & institutionLogos;
-- 
GitLab


From dcf95e0e24b3c08b502ecd444bbf1dd368259604 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 20 Mar 2025 12:43:09 +0100
Subject: [PATCH 47/55] more refactoring for simplification of details API
 implementation

---
 src/app/api/details/route.ts | 35 ++++++++++-------------------------
 1 file changed, 10 insertions(+), 25 deletions(-)

diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index f046419..5a42a08 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -1,12 +1,6 @@
 import { type NextRequest } from "next/server";
 
-import {
-  detailsParamsType,
-  detailsSchema,
-  ResultItem,
-  SolrResponseDocsType,
-  SolrResponseType,
-} from "@/types/types";
+import { detailsParamsType, detailsSchema, SolrResponseType } from "@/types/types";
 import { SOLR_QUERY_DEFAULTS, INSTITUTE_ROR_LOGOS } from "@api/config/config";
 import {
   createFacetParams,
@@ -47,28 +41,19 @@ export const GET = async (req: NextRequest) => {
         { error: { message: "No results found for given ID and documentType" } },
         { status: 400 }
       );
-    } else {
-      const solrResponseRecord: ResultItem[] = solrResponse.response.docs.map(
-        (record: SolrResponseDocsType) => createResultItem(record)
-      );
-      const solrResultItem = solrResponseRecord[0];
-
-      if (documentType === "institutions" && solrResultItem.id.startsWith("https://ror.org")) {
-        const enrichedRecords = await getEnrichedRecords(solrResponseRecord);
-        const enrichedRecord = enrichedRecords[0];
-        const logoItem = INSTITUTE_ROR_LOGOS.find((item) => item.id === enrichedRecord.id);
+    }
 
-        return Response.json(
-          {
-            ...enrichedRecord,
-            ...(logoItem && { logo: logoItem.logo, favicon: logoItem.favicon }),
-          },
-          { status: 200 }
-        );
-      }
+    const solrResultItem = createResultItem(solrResponse.response.docs[0]);
 
+    if (documentType !== "institutions" || !solrResultItem.id.startsWith("https://ror.org")) {
       return Response.json(solrResultItem, { status: 200 });
     }
+
+    const enrichedRecord = (await getEnrichedRecords([solrResultItem]))[0];
+    const logoItem = INSTITUTE_ROR_LOGOS.find((item) => item.id === enrichedRecord.id);
+    const logoInfo = logoItem && { logo: logoItem.logo, favicon: logoItem.favicon };
+
+    return Response.json({ ...enrichedRecord, ...logoInfo }, { status: 200 });
   } catch (error) {
     console.error("Error while handling details", error);
     return Response.json(
-- 
GitLab


From df75a7c5d8ca317f97cf5d117654f08437271443 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Thu, 20 Mar 2025 13:55:39 +0100
Subject: [PATCH 48/55] changed the status code for error when no document is
 found for a given set of parameters

---
 src/app/api/__tests__/api/details.test.ts | 4 ++--
 src/app/api/details/route.ts              | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/app/api/__tests__/api/details.test.ts b/src/app/api/__tests__/api/details.test.ts
index 11ef562..eda6f70 100644
--- a/src/app/api/__tests__/api/details.test.ts
+++ b/src/app/api/__tests__/api/details.test.ts
@@ -89,7 +89,7 @@ describe("unit tests for /details API Endpoint", () => {
 
     const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
-    expect(response.status).toBe(400);
+    expect(response.status).toBe(404);
     expect(jsonResult).toMatchObject(misformedIdCorrectDocType);
   });
 
@@ -105,7 +105,7 @@ describe("unit tests for /details API Endpoint", () => {
 
     const response = (await GET(req)) as Response;
     const jsonResult = await response.json();
-    expect(response.status).toBe(400);
+    expect(response.status).toBe(404);
     expect(jsonResult).toMatchObject(correctIdMismatchedDocType);
   });
 
diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 5a42a08..48e5e1e 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -39,7 +39,7 @@ export const GET = async (req: NextRequest) => {
     if (solrResponse.response.numFound === 0) {
       return Response.json(
         { error: { message: "No results found for given ID and documentType" } },
-        { status: 400 }
+        { status: 404 }
       );
     }
 
-- 
GitLab


From 9467420474c571d760656dfc9c6ebab0efccc759 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Tue, 25 Mar 2025 11:43:54 +0100
Subject: [PATCH 49/55] refactored code to handle snake case codes by
 transforming them for further calculation into camelCase, removed eslint
 exceptions

---
 .eslintrc.json              | 17 +----------------
 src/app/api/utils/shared.ts | 34 ++++++++++++++++++----------------
 2 files changed, 19 insertions(+), 32 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index 918a7be..8165096 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -25,20 +25,5 @@
     "default-case-last": "error",
     "max-lines-per-function": ["error", 500],
     "react/no-is-mounted": "off" //debug the linting issue when this is on
-  },
-  "overrides": [
-    {
-      "files": ["src/app/api/**/*.{js,ts}"],
-      "rules": {
-        "camelcase": "off"
-      }
-    }
-    // {
-    //   "files": ["src/app/**/*.{js,ts,jsx,tsx}"],
-    //   "excludedFiles": ["src/app/api/**/*.{js,ts}"],
-    //   "rules": {
-    //     "no-console": "error"
-    //   }
-    // }
-  ]
+  }
 }
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index 5a2d2a1..675a897 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -184,27 +184,29 @@ export const handleDetailsParamErrors = (errors: ZodIssue[]) => {
 
     const errorMessages = {
       custom: message === "ID cannot be an empty string" && message,
-      invalid_union: message === "Invalid input" && "Document type submitted is invalid",
-      invalid_type: message === "Required" && "Request missing id parameter",
+      invalidUnion: message === "Invalid input" && "Document type submitted is invalid",
+      invalidType: message === "Required" && "Request missing id parameter",
     };
 
-    const errorMessage = errorMessages[code as keyof typeof errorMessages];
-    if (errorMessage) return errorResponse(errorMessage);
+    const camelCaseCode = getCamelCaseCode(code);
+    const errorMessage = errorMessages[camelCaseCode as keyof typeof errorMessages];
+    if (errorMessage) {
+      return errorResponse(errorMessage);
+    }
   }
 
-  // TODO: Is the following check even required?
-  const isMultiParamError =
-    errors.length > 1 &&
-    errors.every(
-      (error) =>
-        (error.code === "invalid_type" && error.message === "Required") ||
-        (error.code === "invalid_union" && error.message === "Invalid input")
-    );
-
-  if (isMultiParamError) {
-    const missingParams = errors.map((e) => e.path[0]).join(" and ");
-    return errorResponse(`Request missing ${missingParams} parameters`);
+  const missingParams = errors.map((e) => e.path[0]).join(" and ");
+  return errorResponse(`Request missing ${missingParams} parameters`);
+};
+
+const getCamelCaseCode = (code: string) => {
+  const codeArray = code.split("_");
+  if (codeArray.length === 2) {
+    const codeKey = codeArray[1]?.charAt(0)?.toUpperCase() + codeArray[1].slice(1);
+    codeArray.pop();
+    return codeArray.join() + codeKey;
   }
+  return "custom";
 };
 
 export const getEnrichedRecords = async (rorRecords: ResultItem[]): Promise<ResultItem[]> => {
-- 
GitLab


From 34562f5bb9bead87434c00713b2b896564a1afa7 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 7 Apr 2025 10:18:29 +0200
Subject: [PATCH 50/55] moving config file to the utils folder

---
 src/app/api/details/route.ts                                    | 2 +-
 src/app/api/{config => utils}/config.ts                         | 0
 src/app/api/utils/shared.ts                                     | 2 +-
 src/app/api/utils/solrQuery.ts                                  | 2 +-
 src/components/app/results/ListResults/ResultItem.tsx           | 2 +-
 .../app/results/ListResults/ResultItem/Relationships.tsx        | 2 +-
 src/types/types.ts                                              | 2 +-
 7 files changed, 6 insertions(+), 6 deletions(-)
 rename src/app/api/{config => utils}/config.ts (100%)

diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 48e5e1e..6e54376 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -1,7 +1,7 @@
 import { type NextRequest } from "next/server";
 
+import { SOLR_QUERY_DEFAULTS, INSTITUTE_ROR_LOGOS } from "@/app/api/utils/config";
 import { detailsParamsType, detailsSchema, SolrResponseType } from "@/types/types";
-import { SOLR_QUERY_DEFAULTS, INSTITUTE_ROR_LOGOS } from "@api/config/config";
 import {
   createFacetParams,
   createResultItem,
diff --git a/src/app/api/config/config.ts b/src/app/api/utils/config.ts
similarity index 100%
rename from src/app/api/config/config.ts
rename to src/app/api/utils/config.ts
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index 675a897..9e29c95 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -9,7 +9,7 @@ import {
   SOLR_RESULT_ITEM_KEYS,
   SOLR_RESULT_CONFIG_KEYS,
   INITIAL_CATECORY_COUNT_MAP,
-} from "@/app/api/config/config";
+} from "@/app/api/utils/config";
 import {
   type Category,
   type SOLRCategories,
diff --git a/src/app/api/utils/solrQuery.ts b/src/app/api/utils/solrQuery.ts
index b4fd9ef..38ffbbb 100644
--- a/src/app/api/utils/solrQuery.ts
+++ b/src/app/api/utils/solrQuery.ts
@@ -3,7 +3,7 @@ import {
   DEFAULT_FACET_FIELDS,
   FACET_INTERVAL_DEFAULTS,
   SOLR_QUERY_DEFAULTS,
-} from "@/app/api/config/config";
+} from "@/app/api/utils/config";
 import { FacetFieldKeys, Formats } from "@/types/types";
 
 const SOLR_URL = new URL(process.env.NEXT_PRIVATE_SOLR_SERVICE_URL || "");
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index c63b21c..ca61180 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -6,7 +6,7 @@ import { useRouter } from "next/navigation";
 import { useTranslations } from "next-intl";
 import { useEffect, useRef, useState } from "react";
 
-import { INSTITUTE_ROR_LOGOS } from "@/app/api/config/config";
+import { INSTITUTE_ROR_LOGOS } from "@/app/api/utils/config"; // TODO: remove this import when we implement ror enrichment in the API layer
 import ExternalLink from "@/components/ExternalLink";
 import Relationships from "@/components/app/results/ListResults/ResultItem/Relationships";
 import { Link } from "@/i18n/routing";
diff --git a/src/components/app/results/ListResults/ResultItem/Relationships.tsx b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
index de00642..b12d3df 100644
--- a/src/components/app/results/ListResults/ResultItem/Relationships.tsx
+++ b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
@@ -2,7 +2,7 @@ import Image from "next/image";
 import { useTranslations } from "next-intl";
 import React, { useEffect, useRef, useState } from "react";
 
-import { INSTITUTE_ROR_LOGOS } from "@/app/api/config/config";
+import { INSTITUTE_ROR_LOGOS } from "@/app/api/utils/config"; // TODO: remove this import when we implement ror enrichment in the API layer
 import { Link } from "@/i18n/routing";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 
diff --git a/src/types/types.ts b/src/types/types.ts
index fb852ae..82e9d11 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -5,7 +5,7 @@ import {
   SOLR_RESULT_ITEM_KEYS,
   SOLR_RESULT_CONFIG_KEYS,
   SOLR_CATEGORIES,
-} from "@/app/api/config/config";
+} from "@/app/api/utils/config";
 
 // ================== SOLR DATA SCHEMES =================
 export type Formats = {
-- 
GitLab


From 28f9928170dc91a940b3d28959aa5e11bcb8c01e Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 7 Apr 2025 10:36:27 +0200
Subject: [PATCH 51/55] handled sending error response from within the route
 instead of a helper function

---
 src/app/api/details/route.ts | 3 ++-
 src/app/api/utils/shared.ts  | 7 ++-----
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 6e54376..00c5462 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -18,7 +18,8 @@ export const GET = async (req: NextRequest) => {
 
     if (!requestBody.success) {
       const { errors } = requestBody.error;
-      return handleDetailsParamErrors(errors);
+      const message = handleDetailsParamErrors(errors);
+      return Response.json({ error: { message, errors } }, { status: 400 });
     }
 
     const { id, documentType }: detailsParamsType = requestBody.data;
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index 9e29c95..1b47cfb 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -176,9 +176,6 @@ export const createResultFilters = (
     .reduce((acc, curr) => acc?.concat(curr), []);
 
 export const handleDetailsParamErrors = (errors: ZodIssue[]) => {
-  const errorResponse = (message: string) =>
-    Response.json({ error: { message, errors } }, { status: 400 });
-
   if (errors.length === 1) {
     const { code, message } = errors[0];
 
@@ -191,12 +188,12 @@ export const handleDetailsParamErrors = (errors: ZodIssue[]) => {
     const camelCaseCode = getCamelCaseCode(code);
     const errorMessage = errorMessages[camelCaseCode as keyof typeof errorMessages];
     if (errorMessage) {
-      return errorResponse(errorMessage);
+      return errorMessage;
     }
   }
 
   const missingParams = errors.map((e) => e.path[0]).join(" and ");
-  return errorResponse(`Request missing ${missingParams} parameters`);
+  return `Request missing ${missingParams} parameters`;
 };
 
 const getCamelCaseCode = (code: string) => {
-- 
GitLab


From ef3da51c2af5b2e8b83d6712ee755b20dcd1aff1 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Mon, 7 Apr 2025 11:07:59 +0200
Subject: [PATCH 52/55] better handling of URLsearchParams for parsing by zod
 parser

---
 src/app/api/details/route.ts | 6 +++---
 src/app/api/search/route.ts  | 6 +++---
 src/app/api/utils/shared.ts  | 4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 00c5462..9882acb 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -5,7 +5,7 @@ import { detailsParamsType, detailsSchema, SolrResponseType } from "@/types/type
 import {
   createFacetParams,
   createResultItem,
-  createSearchParamsMap,
+  createSearchParamsObject,
   handleDetailsParamErrors,
   getEnrichedRecords,
 } from "@api/utils/shared";
@@ -13,8 +13,8 @@ import SolrQuery from "@api/utils/solrQuery";
 
 export const GET = async (req: NextRequest) => {
   try {
-    const detailsParamsMap = createSearchParamsMap(req.nextUrl.searchParams);
-    const requestBody = detailsSchema.safeParse(Object.fromEntries(detailsParamsMap));
+    const detailsParamsObject = createSearchParamsObject(req.nextUrl.searchParams);
+    const requestBody = detailsSchema.safeParse(detailsParamsObject);
 
     if (!requestBody.success) {
       const { errors } = requestBody.error;
diff --git a/src/app/api/search/route.ts b/src/app/api/search/route.ts
index 013a873..1cca026 100644
--- a/src/app/api/search/route.ts
+++ b/src/app/api/search/route.ts
@@ -9,7 +9,7 @@ import {
   type SolrResponseType,
 } from "@/types/types";
 import {
-  createSearchParamsMap,
+  createSearchParamsObject,
   createFacetParams,
   createResultFilters,
   createResultItem,
@@ -20,8 +20,8 @@ import SolrQuery from "@api/utils/solrQuery";
 
 export const GET = async (req: NextRequest) => {
   try {
-    const searchParamsMap = createSearchParamsMap(req.nextUrl.searchParams);
-    const requestBody = searchSchema.safeParse(Object.fromEntries(searchParamsMap));
+    const searchParamsObject = createSearchParamsObject(req.nextUrl.searchParams);
+    const requestBody = searchSchema.safeParse(searchParamsObject);
 
     if (!requestBody.success) {
       const { errors } = requestBody.error;
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index 1b47cfb..7319e58 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -26,7 +26,7 @@ import {
   type ResultKeys,
 } from "@/types/types";
 
-export function createSearchParamsMap(nextParams: URLSearchParams) {
+export function createSearchParamsObject(nextParams: URLSearchParams): Record<string, string> {
   const searchParams = new Map();
 
   for (const [key, value] of nextParams.entries()) {
@@ -37,7 +37,7 @@ export function createSearchParamsMap(nextParams: URLSearchParams) {
     }
   }
 
-  return searchParams;
+  return Object.fromEntries(searchParams);
 }
 
 export function isFacetIntervalFieldKey(item?: FacetFieldKeys): item is FacetIntervalFieldKeys {
-- 
GitLab


From 3592f424dcda601bf99bad9468a42778718de676 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 16 Apr 2025 10:55:08 +0200
Subject: [PATCH 53/55] fixed import issue to be from /app to /api

---
 src/app/api/__tests__/api/search.test.ts | 38 ++++++++++++------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/src/app/api/__tests__/api/search.test.ts b/src/app/api/__tests__/api/search.test.ts
index a6f2e07..7746d59 100644
--- a/src/app/api/__tests__/api/search.test.ts
+++ b/src/app/api/__tests__/api/search.test.ts
@@ -1,24 +1,24 @@
 import { NextRequest } from "next/server";
 
-import solrWithSingleDifferentFilter from "@/app/api/__tests__/__mocks__/solrResults/10.withSingleDifferentFilters.json";
-import solrWithMultipleDifferentFilter from "@/app/api/__tests__/__mocks__/solrResults/11.withMultipleDifferentFilters.json";
-import solrNoParamsSearch from "@/app/api/__tests__/__mocks__/solrResults/4.noParamsSearch.json";
-import solrSearchTextResponse from "@/app/api/__tests__/__mocks__/solrResults/5.onlySearchText.json";
-import solrInstitutionsResponse from "@/app/api/__tests__/__mocks__/solrResults/6.onlyDocumentType.json";
-import solrDocAndTextSearch from "@/app/api/__tests__/__mocks__/solrResults/7.docAndTextSearch.json";
-import solrWithSingleFilter from "@/app/api/__tests__/__mocks__/solrResults/8.withSingleFilter.json";
-import solrWithMulitpleSameFilter from "@/app/api/__tests__/__mocks__/solrResults/9.withMultipleSameFilters.json";
-import singleInvalidParam from "@/app/api/__tests__/expectedApiResults/1.singleInvalidParam.json";
-import withSingleDifferentFilters from "@/app/api/__tests__/expectedApiResults/10.withSingleDifferentFilters.json";
-import withMultipleDifferentFilters from "@/app/api/__tests__/expectedApiResults/11.withMultipleDifferentFilters.json";
-import multipleInvalidParams from "@/app/api/__tests__/expectedApiResults/2.multipleInvalidParams.json";
-import wrongDocType from "@/app/api/__tests__/expectedApiResults/3.wrongDocType.json";
-import noParamsSearch from "@/app/api/__tests__/expectedApiResults/4.noParamsSearch.json";
-import searchTextApiResponse from "@/app/api/__tests__/expectedApiResults/5.onlySearchText.json";
-import institutionsResponse from "@/app/api/__tests__/expectedApiResults/6.onlyDocumentType.json";
-import docAndTextSearch from "@/app/api/__tests__/expectedApiResults/7.docAndTextSearch.json";
-import withSingleFilter from "@/app/api/__tests__/expectedApiResults/8.withSingleFilter.json";
-import withMultipleSameFilters from "@/app/api/__tests__/expectedApiResults/9.withMultipleSameFilters.json";
+import solrWithSingleDifferentFilter from "@api/__tests__/__mocks__/solrResults/10.withSingleDifferentFilters.json";
+import solrWithMultipleDifferentFilter from "@api/__tests__/__mocks__/solrResults/11.withMultipleDifferentFilters.json";
+import solrNoParamsSearch from "@api/__tests__/__mocks__/solrResults/4.noParamsSearch.json";
+import solrSearchTextResponse from "@api/__tests__/__mocks__/solrResults/5.onlySearchText.json";
+import solrInstitutionsResponse from "@api/__tests__/__mocks__/solrResults/6.onlyDocumentType.json";
+import solrDocAndTextSearch from "@api/__tests__/__mocks__/solrResults/7.docAndTextSearch.json";
+import solrWithSingleFilter from "@api/__tests__/__mocks__/solrResults/8.withSingleFilter.json";
+import solrWithMulitpleSameFilter from "@api/__tests__/__mocks__/solrResults/9.withMultipleSameFilters.json";
+import singleInvalidParam from "@api/__tests__/expectedApiResults/1.singleInvalidParam.json";
+import withSingleDifferentFilters from "@api/__tests__/expectedApiResults/10.withSingleDifferentFilters.json";
+import withMultipleDifferentFilters from "@api/__tests__/expectedApiResults/11.withMultipleDifferentFilters.json";
+import multipleInvalidParams from "@api/__tests__/expectedApiResults/2.multipleInvalidParams.json";
+import wrongDocType from "@api/__tests__/expectedApiResults/3.wrongDocType.json";
+import noParamsSearch from "@api/__tests__/expectedApiResults/4.noParamsSearch.json";
+import searchTextApiResponse from "@api/__tests__/expectedApiResults/5.onlySearchText.json";
+import institutionsResponse from "@api/__tests__/expectedApiResults/6.onlyDocumentType.json";
+import docAndTextSearch from "@api/__tests__/expectedApiResults/7.docAndTextSearch.json";
+import withSingleFilter from "@api/__tests__/expectedApiResults/8.withSingleFilter.json";
+import withMultipleSameFilters from "@api/__tests__/expectedApiResults/9.withMultipleSameFilters.json";
 import { GET } from "@api/search/route";
 
 describe("/search API Endpoint", () => {
-- 
GitLab


From 7ce4bed2bd0b23d0b6069f1f2e274ed9e389da97 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 16 Apr 2025 10:58:13 +0200
Subject: [PATCH 54/55] simplified logic to find logoItem in the details route

---
 src/app/api/details/route.ts | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 9882acb..0343b57 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -51,8 +51,7 @@ export const GET = async (req: NextRequest) => {
     }
 
     const enrichedRecord = (await getEnrichedRecords([solrResultItem]))[0];
-    const logoItem = INSTITUTE_ROR_LOGOS.find((item) => item.id === enrichedRecord.id);
-    const logoInfo = logoItem && { logo: logoItem.logo, favicon: logoItem.favicon };
+    const logoInfo = INSTITUTE_ROR_LOGOS.find((item) => item.id === enrichedRecord.id);
 
     return Response.json({ ...enrichedRecord, ...logoInfo }, { status: 200 });
   } catch (error) {
-- 
GitLab


From 7ec4bb42e294ed56af0714e87c4c4359c5d6db30 Mon Sep 17 00:00:00 2001
From: FionaDmello <40391218+FionaDmello@users.noreply.github.com>
Date: Wed, 16 Apr 2025 13:15:48 +0200
Subject: [PATCH 55/55] split the config file by concern, and fixed a bug
 pointed by typescript

---
 src/app/api/config/category.ts                |  55 +++
 src/app/api/config/common.ts                  | 103 +++++
 src/app/api/config/solr.ts                    | 190 ++++++++++
 src/app/api/details/route.ts                  |   3 +-
 src/app/api/utils/config.ts                   | 352 ------------------
 src/app/api/utils/shared.ts                   |  50 ++-
 src/app/api/utils/solrQuery.ts                |   4 +-
 .../app/results/ListResults/ResultItem.tsx    |   2 +-
 .../ListResults/ResultItem/Relationships.tsx  |   2 +-
 src/types/types.ts                            |  24 +-
 10 files changed, 388 insertions(+), 397 deletions(-)
 create mode 100644 src/app/api/config/category.ts
 create mode 100644 src/app/api/config/common.ts
 create mode 100644 src/app/api/config/solr.ts
 delete mode 100644 src/app/api/utils/config.ts

diff --git a/src/app/api/config/category.ts b/src/app/api/config/category.ts
new file mode 100644
index 0000000..95c9cb2
--- /dev/null
+++ b/src/app/api/config/category.ts
@@ -0,0 +1,55 @@
+import type { Category, FacetFieldKeys } from "@/types/types";
+
+export const CATEGORIES: Category[] = [
+  {
+    id: "datasets",
+    text: "Datasets",
+    count: 0,
+  },
+  {
+    id: "software",
+    text: "Software",
+    count: 0,
+  },
+  {
+    id: "documents",
+    text: "Documents",
+    count: 0,
+  },
+  {
+    id: "instruments",
+    text: "Instruments",
+    count: 0,
+  },
+  {
+    id: "experts",
+    text: "Experts",
+    count: 0,
+  },
+  {
+    id: "institutions",
+    text: "Institutions",
+    count: 0,
+  },
+  {
+    id: "trainings",
+    text: "Trainings",
+    count: 0,
+  },
+  {
+    id: "projects",
+    text: "Projects",
+    count: 0,
+  },
+];
+
+export const INITIAL_CATECORY_COUNT_MAP: Record<FacetFieldKeys, number> = {
+  experts: 0,
+  documents: 0,
+  datasets: 0,
+  institutions: 0,
+  trainings: 0,
+  projects: 0,
+  software: 0,
+  instruments: 0,
+};
diff --git a/src/app/api/config/common.ts b/src/app/api/config/common.ts
new file mode 100644
index 0000000..14cb7b4
--- /dev/null
+++ b/src/app/api/config/common.ts
@@ -0,0 +1,103 @@
+// TODO: will be moved to solr.ts when ROR enrichment happens in the API layer
+export const INSTITUTE_ROR_LOGOS = [
+  // Helmholtz Association
+  {
+    id: "https://ror.org/0281dp749",
+    favicon:
+      "https://www.helmholtz.de/typo3conf/ext/dreipc_hgf/Resources/Public/Frontend/Build/assets/icons/favicons/icon-228x228.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/9/94/Helmholtz_Association%27s_Logo.svg",
+  },
+  // 18 Helmholtz Centers
+  {
+    id: "https://ror.org/02h2x0161",
+    favicon:
+      "https://www.geomar.de/typo3conf/ext/geomar_provider/Resources/Public/Graphics/favicon/favicon-16x16.png",
+  },
+  {
+    id: "https://ror.org/03qjp1d79",
+    favicon: "https://hereon.de/favicon-16x16.png",
+  },
+  {
+    id: "https://ror.org/04p5ggc03",
+    favicon: "https://www.mdc-berlin.de/sites/default/files/favicons/favicon-16x16.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/3/3f/MDC_Logo_V1_RGB_blue.svg",
+  },
+  {
+    id: "https://ror.org/01js2sh04",
+    favicon: "https://www.desy.de/++resource++desy/images/desy_logo_3c_web.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/5/55/Desy_logo_3c_web.svg",
+  },
+  {
+    id: "https://ror.org/032e6b942",
+    favicon: "https://www.awi.de/_assets/978631966794c5093250775de182779d/Images/AWI/favicon.ico",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/f/f7/AWI_Logo_2017.svg",
+  },
+  {
+    id: "https://ror.org/03d0p2685",
+    favicon:
+      "https://www.helmholtz-hzi.de/_assets/ae8a1fe32f30b295243325c1db1b8058/Icons/Favicons/HZI/favicon-16x16.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/c/cd/Helmholtz-Zentrum_f%C3%BCr_Infektionsforschung_GmbH.jpg",
+  },
+  {
+    id: "https://ror.org/04z8jg394",
+    favicon: "https://www.gfz.de/_assets/addb558b1d0e21da17cab6423afccec8/Icons/favicon.ico",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/8/86/Deutsches-GeoForschungsZentrum-Logo.svg",
+  },
+  {
+    id: "https://ror.org/02aj13c28",
+    favicon: "https://www.helmholtz-berlin.de/favicon.ico",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/6/6b/Helmholtz-Zentrum_Berlin_f%C3%BCr_Materialien_und_Energie_Logo.svg",
+  },
+  {
+    id: "https://ror.org/000h6jb29",
+    favicon: "https://www.ufz.de/static/custom/weblayout/DefaultInternetLayout/img/favicon.ico",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/e/ed/UFZ_Logo_RGB_DE.png",
+  },
+  {
+    id: "https://ror.org/01zy2cs03",
+    favicon: "https://www.hzdr.de/favicon-16x16.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/e/e5/HZDR-LOGO.png",
+  },
+  {
+    id: "https://ror.org/04bwf3e34",
+    favicon: "https://www.dlr.de/icon.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/f/f5/DLR_Logo.svg",
+  },
+  {
+    id: "https://ror.org/02k8cbn47",
+    favicon: "https://www.gsi.de/favicon.ico",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/6/6f/GSI_Logo.svg",
+  },
+  {
+    id: "https://ror.org/00cfam450",
+    favicon:
+      "https://www.helmholtz-munich.de/typo3conf/ext/helmholtz_sitepackage/Resources/Public/Icons/Favicons/favicon-16x16.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/5/51/Helmholtz_Zentrum_M%C3%BCnchen_logo.svg",
+  },
+  {
+    id: "https://ror.org/04t3en479",
+    favicon: "https://www.kit.edu/img/intern/favicon.ico",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/3/3a/Logo_KIT.svg",
+  },
+  {
+    id: "https://ror.org/04cdgtt98",
+    favicon:
+      "https://www.dkfz.de/_assets/5bd5aaeffedb0553dcc3d3be99b60d08/Frontend/Images/Favicon/favicon-16x16.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/d/d9/Deutsches_Krebsforschungszentrum_Logo.svg",
+  },
+  {
+    id: "https://ror.org/02njgxr09",
+    favicon: "https://cispa.de/images/cispa-logo-on-bright.svg",
+  },
+  {
+    id: "https://ror.org/043j0f473",
+    favicon:
+      "https://www.dzne.de/typo3conf/ext/fe_website/Resources/Public/AppIcons/favicon-16x16.png",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/2/26/DZNE_Logo_CMYK.svg",
+  },
+  {
+    id: "https://ror.org/02nv7yv05",
+    favicon: "https://www.fz-juelich.de/icon.svg",
+    logo: "https://upload.wikimedia.org/wikipedia/commons/4/40/Logo_des_Forschungszentrums_J%C3%BClich_seit_2018.svg",
+  },
+];
diff --git a/src/app/api/config/solr.ts b/src/app/api/config/solr.ts
new file mode 100644
index 0000000..acf331c
--- /dev/null
+++ b/src/app/api/config/solr.ts
@@ -0,0 +1,190 @@
+import type { FacetIntervalFieldKeys, FacetFieldKeys, SOLRCategories } from "@/types/types";
+
+export const AVAILABLE_FACETS: string[] = [
+  "txt_knowsAbout",
+  "txt_knowsLanguage",
+  "txt_nationality",
+  "txt_jobTitle",
+  "txt_contributor",
+  "txt_keywords",
+  "txt_memberOf",
+  "txt_parentOrganization",
+  "id_provider",
+  "id_includedInDataCatalog",
+];
+
+// Facets are what is shown for each entry in the list of the web frontend and can be filtered for
+// Common is for combined types
+const COMMON_FACET_FIELDS = {
+  document: [
+    "txt_keywords",
+    "txt_provider",
+    "txt_license",
+    "txt_contributor",
+    "dt_datePublished",
+    "txt_publisher",
+  ],
+  software: [
+    "txt_license",
+    "txt_keywords",
+    "txt_developmentStatus",
+    "txt_programmingLanguage",
+    "txt_runtimePlatform",
+    "txt_publisher",
+    "txt_version",
+  ],
+};
+
+export const FACET_FIELDS: Record<FacetFieldKeys, string[]> = {
+  experts: [
+    "txt_memberOf",
+    "txt_knowsLanguage",
+    "txt_jobTitle",
+    "txt_knowsAbout",
+    "txt_affiliation",
+    "txt_provider",
+  ],
+  institutions: ["txt_memberOf", "txt_provider"],
+  datasets: [
+    "txt_keywords",
+    "txt_license",
+    "txt_provider",
+    "txt_publisher",
+    "txt_variableMeasured",
+  ],
+  documents: COMMON_FACET_FIELDS["document"],
+  trainings: ["txt_keywords", "txt_provider", "txt_author", "txt_educationalCredentialAwarded"],
+  projects: ["txt_keywords", "txt_provider", "txt_areaServed"],
+  software: COMMON_FACET_FIELDS["software"],
+  instruments: ["txt_keywords"],
+};
+
+export const DEFAULT_FACET_FIELDS: string[] = [
+  "txt_knowsAbout",
+  "name",
+  "txt_knowsLanguage",
+  "txt_nationality",
+  "txt_jobTitle",
+  "txt_contributor",
+  "txt_keywords",
+  "txt_memberOf",
+  "txt_parentOrganization",
+  "id_provider",
+  "has_geom",
+  "id_includedInDataCatalog",
+  "id_identifier",
+  "id",
+  "keys",
+  "type",
+];
+
+export const FACET_INTERVALS: Record<FacetIntervalFieldKeys, string[]> = {
+  documents: [],
+  datasets: [],
+};
+
+export const COMBINED_TYPES: Record<FacetFieldKeys, SOLRCategories[]> = {
+  experts: ["Person"],
+  software: [
+    "SoftwareSourceCode",
+    "SoftwareApplication",
+    "SoftwareLibrary",
+    "WebApplication",
+    "CommandlineApplication",
+  ],
+  datasets: ["Dataset"],
+  documents: [
+    "DigitalDocument",
+    "ScholarlyArticle",
+    "CreativeWork",
+    "Report",
+    "Book",
+    "Thesis",
+    "Chapter",
+    "Article",
+  ],
+  institutions: ["Organization", "DataCatalog"],
+  instruments: ["Instruments"],
+  projects: ["ResearchProject"],
+  trainings: ["Course", "Event"],
+};
+
+//NOTE: https://www.freecodecamp.org/news/javascript-range-create-an-array-of-numbers-with-the-from-method/
+const rangedArray = (start: number, stop: number, step: number): number[] => {
+  return Array.from({ length: (stop - start) / step + 1 }, (value, index) => start + index * step);
+};
+
+export const FACET_INTERVAL_DEFAULTS = ["[*,1800)", "[1800,1900)", "[1900,1950)"];
+
+for (const x of rangedArray(1950, 2010, 10)) {
+  FACET_INTERVAL_DEFAULTS.push(`[${x}, ${x + 10})`);
+}
+for (const x of rangedArray(2010, 2030, 2)) {
+  FACET_INTERVAL_DEFAULTS.push(`[${x}, ${x + 2})`);
+}
+
+export const SOLR_QUERY_DEFAULTS = {
+  rows: 10,
+  start: 0,
+  facetMinCount: 1,
+  query: "*:*",
+  sort: "score desc, indexed_ts desc",
+  facet: true,
+  facetStartYearLimit: 30,
+  facetEndYearLimit: 30,
+  qop: "AND",
+  defType: "edismax",
+  qf: "name^4 txt_keywords^2 text",
+};
+
+export const SOLR_RESULT_ITEM_KEYS = [
+  "id",
+  "name",
+  "type",
+  "description",
+  "txt_identifier",
+  "txt_keywords",
+  "txt_includedInDataCatalog",
+  "txt_sameAs",
+  "txt_email",
+  "txt_affiliation",
+  "txt_author",
+  "txt_creator",
+  "txt_publisher",
+  "txt_contributor",
+  "txt_version",
+  "txt_license",
+  "txt_url",
+  "txt_codeRepository",
+  "txt_provider",
+  "txt_endDate",
+  "txt_location",
+  "txt_startDate",
+  "txt_performer",
+] as const;
+
+export const SOLR_RESULT_CONFIG_KEYS = ["index_id", "_version_", "indexed_ts"] as const;
+
+export const SOLR_CATEGORIES = [
+  "DigitalDocument",
+  "Dataset",
+  "Person",
+  "Organization",
+  "ScholarlyArticle",
+  "CreativeWork",
+  "DataCatalog",
+  "SoftwareSourceCode",
+  "Report",
+  "Book",
+  "SoftwareApplication",
+  "Event",
+  "Thesis",
+  "Article",
+  "SoftwareLibrary",
+  "WebApplication",
+  "CommandlineApplication",
+  "Chapter",
+  "ResearchProject",
+  "Course",
+  "Instruments",
+] as const;
diff --git a/src/app/api/details/route.ts b/src/app/api/details/route.ts
index 0343b57..df95bec 100644
--- a/src/app/api/details/route.ts
+++ b/src/app/api/details/route.ts
@@ -1,7 +1,8 @@
 import { type NextRequest } from "next/server";
 
-import { SOLR_QUERY_DEFAULTS, INSTITUTE_ROR_LOGOS } from "@/app/api/utils/config";
 import { detailsParamsType, detailsSchema, SolrResponseType } from "@/types/types";
+import { INSTITUTE_ROR_LOGOS } from "@api/config/common";
+import { SOLR_QUERY_DEFAULTS } from "@api/config/solr";
 import {
   createFacetParams,
   createResultItem,
diff --git a/src/app/api/utils/config.ts b/src/app/api/utils/config.ts
deleted file mode 100644
index 30a16bb..0000000
--- a/src/app/api/utils/config.ts
+++ /dev/null
@@ -1,352 +0,0 @@
-import type {
-  Category,
-  FacetIntervalFieldKeys,
-  FacetFieldKeys,
-  SOLRCategories,
-} from "@/types/types";
-
-export const CATEGORIES: Category[] = [
-  {
-    id: "datasets",
-    text: "Datasets",
-    count: 0,
-  },
-  {
-    id: "software",
-    text: "Software",
-    count: 0,
-  },
-  {
-    id: "documents",
-    text: "Documents",
-    count: 0,
-  },
-  {
-    id: "instruments",
-    text: "Instruments",
-    count: 0,
-  },
-  {
-    id: "experts",
-    text: "Experts",
-    count: 0,
-  },
-  {
-    id: "institutions",
-    text: "Institutions",
-    count: 0,
-  },
-  {
-    id: "trainings",
-    text: "Trainings",
-    count: 0,
-  },
-  {
-    id: "projects",
-    text: "Projects",
-    count: 0,
-  },
-];
-
-export const INITIAL_CATECORY_COUNT_MAP: Record<FacetFieldKeys, number> = {
-  experts: 0,
-  documents: 0,
-  datasets: 0,
-  institutions: 0,
-  trainings: 0,
-  projects: 0,
-  software: 0,
-  instruments: 0,
-};
-
-export const AVAILABLE_FACETS: string[] = [
-  "txt_knowsAbout",
-  "txt_knowsLanguage",
-  "txt_nationality",
-  "txt_jobTitle",
-  "txt_contributor",
-  "txt_keywords",
-  "txt_memberOf",
-  "txt_parentOrganization",
-  "id_provider",
-  "id_includedInDataCatalog",
-];
-
-// Facets are what is shown for each entry in the list of the web frontend and can be filtered for
-// Common is for combined types
-const COMMON_FACET_FIELDS = {
-  document: [
-    "txt_keywords",
-    "txt_provider",
-    "txt_license",
-    "txt_contributor",
-    "dt_datePublished",
-    "txt_publisher",
-  ],
-  software: [
-    "txt_license",
-    "txt_keywords",
-    "txt_developmentStatus",
-    "txt_programmingLanguage",
-    "txt_runtimePlatform",
-    "txt_publisher",
-    "txt_version",
-  ],
-};
-
-export const FACET_FIELDS: Record<FacetFieldKeys, string[]> = {
-  experts: [
-    "txt_memberOf",
-    "txt_knowsLanguage",
-    "txt_jobTitle",
-    "txt_knowsAbout",
-    "txt_affiliation",
-    "txt_provider",
-  ],
-  institutions: ["txt_memberOf", "txt_provider"],
-  datasets: [
-    "txt_keywords",
-    "txt_license",
-    "txt_provider",
-    "txt_publisher",
-    "txt_variableMeasured",
-  ],
-  documents: COMMON_FACET_FIELDS["document"],
-  trainings: ["txt_keywords", "txt_provider", "txt_author", "txt_educationalCredentialAwarded"],
-  projects: ["txt_keywords", "txt_provider", "txt_areaServed"],
-  software: COMMON_FACET_FIELDS["software"],
-  instruments: ["txt_keywords"],
-};
-
-export const DEFAULT_FACET_FIELDS: string[] = [
-  "txt_knowsAbout",
-  "name",
-  "txt_knowsLanguage",
-  "txt_nationality",
-  "txt_jobTitle",
-  "txt_contributor",
-  "txt_keywords",
-  "txt_memberOf",
-  "txt_parentOrganization",
-  "id_provider",
-  "has_geom",
-  "id_includedInDataCatalog",
-  "id_identifier",
-  "id",
-  "keys",
-  "type",
-];
-
-export const FACET_INTERVALS: Record<FacetIntervalFieldKeys, string[]> = {
-  documents: [],
-  datasets: [],
-};
-
-export const COMBINED_TYPES: Record<FacetFieldKeys, SOLRCategories[]> = {
-  experts: ["Person"],
-  software: [
-    "SoftwareSourceCode",
-    "SoftwareApplication",
-    "SoftwareLibrary",
-    "WebApplication",
-    "CommandlineApplication",
-  ],
-  datasets: ["Dataset"],
-  documents: [
-    "DigitalDocument",
-    "ScholarlyArticle",
-    "CreativeWork",
-    "Report",
-    "Book",
-    "Thesis",
-    "Chapter",
-    "Article",
-  ],
-  institutions: ["Organization", "DataCatalog"],
-  instruments: ["Instruments"],
-  projects: ["ResearchProject"],
-  trainings: ["Course", "Event"],
-};
-
-//NOTE: https://www.freecodecamp.org/news/javascript-range-create-an-array-of-numbers-with-the-from-method/
-const rangedArray = (start: number, stop: number, step: number): number[] => {
-  return Array.from({ length: (stop - start) / step + 1 }, (value, index) => start + index * step);
-};
-
-export const FACET_INTERVAL_DEFAULTS = ["[*,1800)", "[1800,1900)", "[1900,1950)"];
-
-for (const x of rangedArray(1950, 2010, 10)) {
-  FACET_INTERVAL_DEFAULTS.push(`[${x}, ${x + 10})`);
-}
-for (const x of rangedArray(2010, 2030, 2)) {
-  FACET_INTERVAL_DEFAULTS.push(`[${x}, ${x + 2})`);
-}
-
-export const SOLR_QUERY_DEFAULTS = {
-  rows: 10,
-  start: 0,
-  facetMinCount: 1,
-  query: "*:*",
-  sort: "score desc, indexed_ts desc",
-  facet: true,
-  facetStartYearLimit: 30,
-  facetEndYearLimit: 30,
-  qop: "AND",
-  defType: "edismax",
-  qf: "name^4 txt_keywords^2 text",
-};
-
-export const SOLR_RESULT_ITEM_KEYS = [
-  "id",
-  "name",
-  "type",
-  "description",
-  "txt_identifier",
-  "txt_keywords",
-  "txt_includedInDataCatalog",
-  "txt_sameAs",
-  "txt_email",
-  "txt_affiliation",
-  "txt_author",
-  "txt_creator",
-  "txt_publisher",
-  "txt_contributor",
-  "txt_version",
-  "txt_license",
-  "txt_url",
-  "txt_codeRepository",
-  "txt_provider",
-  "txt_endDate",
-  "txt_location",
-  "txt_startDate",
-  "txt_performer",
-] as const;
-
-export const SOLR_RESULT_CONFIG_KEYS = ["index_id", "_version_", "indexed_ts"] as const;
-
-export const SOLR_CATEGORIES = [
-  "DigitalDocument",
-  "Dataset",
-  "Person",
-  "Organization",
-  "ScholarlyArticle",
-  "CreativeWork",
-  "DataCatalog",
-  "SoftwareSourceCode",
-  "Report",
-  "Book",
-  "SoftwareApplication",
-  "Event",
-  "Thesis",
-  "Article",
-  "SoftwareLibrary",
-  "WebApplication",
-  "CommandlineApplication",
-  "Chapter",
-  "ResearchProject",
-  "Course",
-  "Instruments",
-] as const;
-
-export const INSTITUTE_ROR_LOGOS = [
-  // Helmholtz Association
-  {
-    id: "https://ror.org/0281dp749",
-    favicon:
-      "https://www.helmholtz.de/typo3conf/ext/dreipc_hgf/Resources/Public/Frontend/Build/assets/icons/favicons/icon-228x228.png",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/9/94/Helmholtz_Association%27s_Logo.svg",
-  },
-  // 18 Helmholtz Centers
-  {
-    id: "https://ror.org/02h2x0161",
-    favicon:
-      "https://www.geomar.de/typo3conf/ext/geomar_provider/Resources/Public/Graphics/favicon/favicon-16x16.png",
-  },
-  {
-    id: "https://ror.org/03qjp1d79",
-    favicon: "https://hereon.de/favicon-16x16.png",
-  },
-  {
-    id: "https://ror.org/04p5ggc03",
-    favicon: "https://www.mdc-berlin.de/sites/default/files/favicons/favicon-16x16.png",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/3/3f/MDC_Logo_V1_RGB_blue.svg",
-  },
-  {
-    id: "https://ror.org/01js2sh04",
-    favicon: "https://www.desy.de/++resource++desy/images/desy_logo_3c_web.svg",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/5/55/Desy_logo_3c_web.svg",
-  },
-  {
-    id: "https://ror.org/032e6b942",
-    favicon: "https://www.awi.de/_assets/978631966794c5093250775de182779d/Images/AWI/favicon.ico",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/f/f7/AWI_Logo_2017.svg",
-  },
-  {
-    id: "https://ror.org/03d0p2685",
-    favicon:
-      "https://www.helmholtz-hzi.de/_assets/ae8a1fe32f30b295243325c1db1b8058/Icons/Favicons/HZI/favicon-16x16.png",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/c/cd/Helmholtz-Zentrum_f%C3%BCr_Infektionsforschung_GmbH.jpg",
-  },
-  {
-    id: "https://ror.org/04z8jg394",
-    favicon: "https://www.gfz.de/_assets/addb558b1d0e21da17cab6423afccec8/Icons/favicon.ico",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/8/86/Deutsches-GeoForschungsZentrum-Logo.svg",
-  },
-  {
-    id: "https://ror.org/02aj13c28",
-    favicon: "https://www.helmholtz-berlin.de/favicon.ico",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/6/6b/Helmholtz-Zentrum_Berlin_f%C3%BCr_Materialien_und_Energie_Logo.svg",
-  },
-  {
-    id: "https://ror.org/000h6jb29",
-    favicon: "https://www.ufz.de/static/custom/weblayout/DefaultInternetLayout/img/favicon.ico",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/e/ed/UFZ_Logo_RGB_DE.png",
-  },
-  {
-    id: "https://ror.org/01zy2cs03",
-    favicon: "https://www.hzdr.de/favicon-16x16.png",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/e/e5/HZDR-LOGO.png",
-  },
-  {
-    id: "https://ror.org/04bwf3e34",
-    favicon: "https://www.dlr.de/icon.svg",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/f/f5/DLR_Logo.svg",
-  },
-  {
-    id: "https://ror.org/02k8cbn47",
-    favicon: "https://www.gsi.de/favicon.ico",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/6/6f/GSI_Logo.svg",
-  },
-  {
-    id: "https://ror.org/00cfam450",
-    favicon:
-      "https://www.helmholtz-munich.de/typo3conf/ext/helmholtz_sitepackage/Resources/Public/Icons/Favicons/favicon-16x16.png",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/5/51/Helmholtz_Zentrum_M%C3%BCnchen_logo.svg",
-  },
-  {
-    id: "https://ror.org/04t3en479",
-    favicon: "https://www.kit.edu/img/intern/favicon.ico",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/3/3a/Logo_KIT.svg",
-  },
-  {
-    id: "https://ror.org/04cdgtt98",
-    favicon:
-      "https://www.dkfz.de/_assets/5bd5aaeffedb0553dcc3d3be99b60d08/Frontend/Images/Favicon/favicon-16x16.png",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/d/d9/Deutsches_Krebsforschungszentrum_Logo.svg",
-  },
-  {
-    id: "https://ror.org/02njgxr09",
-    favicon: "https://cispa.de/images/cispa-logo-on-bright.svg",
-  },
-  {
-    id: "https://ror.org/043j0f473",
-    favicon:
-      "https://www.dzne.de/typo3conf/ext/fe_website/Resources/Public/AppIcons/favicon-16x16.png",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/2/26/DZNE_Logo_CMYK.svg",
-  },
-  {
-    id: "https://ror.org/02nv7yv05",
-    favicon: "https://www.fz-juelich.de/icon.svg",
-    logo: "https://upload.wikimedia.org/wikipedia/commons/4/40/Logo_des_Forschungszentrums_J%C3%BClich_seit_2018.svg",
-  },
-];
diff --git a/src/app/api/utils/shared.ts b/src/app/api/utils/shared.ts
index 7319e58..11c46b9 100644
--- a/src/app/api/utils/shared.ts
+++ b/src/app/api/utils/shared.ts
@@ -1,15 +1,5 @@
 import { ZodIssue } from "zod";
 
-import {
-  AVAILABLE_FACETS,
-  FACET_FIELDS,
-  FACET_INTERVALS,
-  CATEGORIES,
-  COMBINED_TYPES,
-  SOLR_RESULT_ITEM_KEYS,
-  SOLR_RESULT_CONFIG_KEYS,
-  INITIAL_CATECORY_COUNT_MAP,
-} from "@/app/api/utils/config";
 import {
   type Category,
   type SOLRCategories,
@@ -18,13 +8,23 @@ import {
   type FacetIntervalFieldKeys,
   type ResultItem,
   type ResultItemKeys,
-  type ResultConfigKeys,
   type SolrResponseDocsType,
   type FilterEntity,
   type ResultDocs,
   type ResultConfig,
   type ResultKeys,
+  type ResultConfigKeys,
+  type RecordConfigType,
 } from "@/types/types";
+import { CATEGORIES, INITIAL_CATECORY_COUNT_MAP } from "@api/config/category";
+import {
+  AVAILABLE_FACETS,
+  FACET_FIELDS,
+  FACET_INTERVALS,
+  COMBINED_TYPES,
+  SOLR_RESULT_ITEM_KEYS,
+  SOLR_RESULT_CONFIG_KEYS,
+} from "@api/config/solr";
 
 export function createSearchParamsObject(nextParams: URLSearchParams): Record<string, string> {
   const searchParams = new Map();
@@ -70,7 +70,6 @@ export function getSolrCategoryCountsMap(
 
 export function updateCategoryCounts(countsMap: Record<SOLRCategories, number>): Category[] {
   const modifiedCategories = structuredClone(CATEGORIES);
-
   return modifiedCategories.map((category: Category) => {
     // the ts signature for Object.entries is [string, any], but we know we are expecting a [facetFieldKeys, SOLRCategories[]]
     // we thus use the as keyword for type assertion - https://learntypescript.dev/07/l1-type-assertions
@@ -80,19 +79,18 @@ export function updateCategoryCounts(countsMap: Record<SOLRCategories, number>):
     ][]) {
       if (category.id === key) {
         category.count = Object.values(
-          // gets me list of all counts in the object obtained from Object.entries
           Object.fromEntries(
-            // from the combinedType obj, for a given key, get subset of all keys  that are also in the solr counts response map
             values
               .filter((solrCategory: SOLRCategories) =>
                 (Object.keys(countsMap) as SOLRCategories[]).includes(solrCategory)
               )
               // chained to subset of COMBINED_TYPES[key], map returns an [[solrCat, count]] which is fed into Object.entries to create a single dict
               .map((solrCategory: SOLRCategories) => [solrCategory, countsMap[solrCategory]])
-          )
-        ).reduce((acc, curr) => acc + curr, 0);
+          ) as Record<SOLRCategories, number>
+        ).reduce<number>((acc: number, curr: number) => acc + curr, 0);
       }
     }
+
     return category;
   });
 }
@@ -117,22 +115,22 @@ export function updateCategoryCountsForSearch(
                 (Object.keys(countsMap) as SOLRCategories[]).includes(solrCategory)
               )
               .map((solrCategory: SOLRCategories) => [solrCategory, countsMap[solrCategory]])
-          )
-        ).reduce((acc, curr) => acc + curr, 0);
+          ) as Record<SOLRCategories, number>
+        ).reduce<number>((acc: number, curr: number) => acc + curr, 0);
       }
     }
   });
-
   return updatedCountsMap;
 }
 
 export const createResultItem = (item: SolrResponseDocsType): ResultItem => {
-  const recordConfigObj = Object.fromEntries(
-    SOLR_RESULT_CONFIG_KEYS.map((key: ResultConfigKeys) => {
-      return [key, item[key]] as [ResultConfigKeys, string];
-    })
-  ) as Record<ResultConfigKeys, string>;
-  const config: ResultConfig = { recordConfig: recordConfigObj };
+  const config: ResultConfig = {
+    recordConfig: Object.fromEntries(
+      SOLR_RESULT_CONFIG_KEYS.map((key: ResultConfigKeys) => {
+        return [key, item[key]];
+      })
+    ) as RecordConfigType,
+  };
 
   // we do this to get rid of key-values that are unnecessary for the frontend
   const filteredKeys: ResultItemKeys[] = item.keys.filter((key: ResultItemKeys) =>
@@ -142,7 +140,7 @@ export const createResultItem = (item: SolrResponseDocsType): ResultItem => {
 
   const records = Object.fromEntries(
     filteredKeys.map((key: ResultItemKeys) => {
-      return [key, item[key]];
+      return [key, item[key as keyof SolrResponseDocsType]];
     })
   ) as ResultDocs;
 
diff --git a/src/app/api/utils/solrQuery.ts b/src/app/api/utils/solrQuery.ts
index 38ffbbb..37cff09 100644
--- a/src/app/api/utils/solrQuery.ts
+++ b/src/app/api/utils/solrQuery.ts
@@ -1,10 +1,10 @@
+import { FacetFieldKeys, Formats } from "@/types/types";
 import {
   COMBINED_TYPES,
   DEFAULT_FACET_FIELDS,
   FACET_INTERVAL_DEFAULTS,
   SOLR_QUERY_DEFAULTS,
-} from "@/app/api/utils/config";
-import { FacetFieldKeys, Formats } from "@/types/types";
+} from "@api/config/solr";
 
 const SOLR_URL = new URL(process.env.NEXT_PRIVATE_SOLR_SERVICE_URL || "");
 
diff --git a/src/components/app/results/ListResults/ResultItem.tsx b/src/components/app/results/ListResults/ResultItem.tsx
index ca61180..2c8bbaf 100644
--- a/src/components/app/results/ListResults/ResultItem.tsx
+++ b/src/components/app/results/ListResults/ResultItem.tsx
@@ -6,7 +6,6 @@ import { useRouter } from "next/navigation";
 import { useTranslations } from "next-intl";
 import { useEffect, useRef, useState } from "react";
 
-import { INSTITUTE_ROR_LOGOS } from "@/app/api/utils/config"; // TODO: remove this import when we implement ror enrichment in the API layer
 import ExternalLink from "@/components/ExternalLink";
 import Relationships from "@/components/app/results/ListResults/ResultItem/Relationships";
 import { Link } from "@/i18n/routing";
@@ -14,6 +13,7 @@ import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
 import RightArrowIcon from "@/resources/images/svg/RightArrowIcon";
 import type { Category, ResultItem as ResultItemType } from "@/types/types";
 import { detailsItemAtom } from "@/utils/atoms";
+import { INSTITUTE_ROR_LOGOS } from "@api/config/common"; // TODO: remove this import when we implement ror enrichment in the API layer
 
 type Props = {
   item: ResultItemType;
diff --git a/src/components/app/results/ListResults/ResultItem/Relationships.tsx b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
index b12d3df..d7d1155 100644
--- a/src/components/app/results/ListResults/ResultItem/Relationships.tsx
+++ b/src/components/app/results/ListResults/ResultItem/Relationships.tsx
@@ -2,9 +2,9 @@ import Image from "next/image";
 import { useTranslations } from "next-intl";
 import React, { useEffect, useRef, useState } from "react";
 
-import { INSTITUTE_ROR_LOGOS } from "@/app/api/utils/config"; // TODO: remove this import when we implement ror enrichment in the API layer
 import { Link } from "@/i18n/routing";
 import ExternalLinkIcon from "@/resources/images/svg/ExternalLinkIcon";
+import { INSTITUTE_ROR_LOGOS } from "@api/config/common"; // TODO: remove this import when we implement ror enrichment in the API layer
 
 type Props = {
   filteredArr: { label: string; type: string; id: string }[];
diff --git a/src/types/types.ts b/src/types/types.ts
index 82e9d11..72838f3 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -1,11 +1,7 @@
 import { StaticImport } from "next/dist/shared/lib/get-img-props";
 import { z } from "zod";
 
-import {
-  SOLR_RESULT_ITEM_KEYS,
-  SOLR_RESULT_CONFIG_KEYS,
-  SOLR_CATEGORIES,
-} from "@/app/api/utils/config";
+import { SOLR_RESULT_ITEM_KEYS, SOLR_RESULT_CONFIG_KEYS, SOLR_CATEGORIES } from "@api/config/solr";
 
 // ================== SOLR DATA SCHEMES =================
 export type Formats = {
@@ -36,10 +32,8 @@ export type SolrResponseDocsType = {
   keys: ResultItemKeys[];
   json_source: string;
   json_uplifted: string;
-  index_id: string;
-  _version_: string;
-  indexed_ts: string;
-} & ResultDocs;
+} & ResultDocs &
+  RecordConfigType;
 
 // this is a pattern combining three ts
 // https://learntypescript.dev/10/l5-deep-immutable#using-const-assertions
@@ -84,11 +78,13 @@ export type ResultDocs = {
 };
 
 export type ResultConfig = {
-  recordConfig: {
-    index_id: string;
-    _version_: string;
-    indexed_ts: string;
-  };
+  recordConfig: RecordConfigType;
+};
+
+export type RecordConfigType = {
+  index_id: string;
+  _version_: string;
+  indexed_ts: string;
 };
 
 export type ResultKeys = { keys: ResultItemKeys[] };
-- 
GitLab