diff --git a/explorer/src/assets/locales/en/en.json b/explorer/src/assets/locales/en/en.json index 3987824e..77187f09 100644 --- a/explorer/src/assets/locales/en/en.json +++ b/explorer/src/assets/locales/en/en.json @@ -52,7 +52,7 @@ "home": { "title": "Your Reputation Under Your Control", "description": "Explore the ecosystem to find out how you can unlock your data from across the web and share it with the world on your own terms", - "exploreEcosystem": "or explore the ecosystem", + "exploreEcosystem": "or explore the ecosystem...", "info": { "issueYourAttestation": "Want to issue your own attestation?", "aboutVerax": "Want to know more about Verax?" @@ -140,6 +140,14 @@ "title": "Revokable", "yes": "Yes", "no": "No" + }, + "list": { + "title": "Explore Portals", + "columns": { + "name": "Portal Name", + "description": "Portal Description", + "owner": "Owner Address" + } } } } diff --git a/explorer/src/assets/logo/verax-logo-dark-mode.svg b/explorer/src/assets/logo/verax-logo-dark-mode.svg index 8a904026..532bc3db 100644 --- a/explorer/src/assets/logo/verax-logo-dark-mode.svg +++ b/explorer/src/assets/logo/verax-logo-dark-mode.svg @@ -1,31 +1,31 @@ - - - - + + + + - + diff --git a/explorer/src/components/NotFoundPage/index.tsx b/explorer/src/components/NotFoundPage/index.tsx index c5da004b..8acf6c2b 100644 --- a/explorer/src/components/NotFoundPage/index.tsx +++ b/explorer/src/components/NotFoundPage/index.tsx @@ -15,10 +15,10 @@ export const NotFoundPage: React.FC = ({ id, page }) => {
-

+

{pageData.title} {pageData.showId && ( - + {decodedId} )} @@ -26,7 +26,7 @@ export const NotFoundPage: React.FC = ({ id, page }) => {

{t("common.actions.goBackTo", { to: page })} diff --git a/explorer/src/components/SearchInput/index.tsx b/explorer/src/components/SearchInput/index.tsx index 857bee64..6bb1ae90 100644 --- a/explorer/src/components/SearchInput/index.tsx +++ b/explorer/src/components/SearchInput/index.tsx @@ -8,7 +8,7 @@ import { keyboard } from "@/constants/keyboard"; import { EQueryParams } from "@/enums/queryParams"; import { useHandleSearch } from "@/hooks/useHandleSearch"; -export const SearchInput: React.FC<{ className?: string }> = ({ className }) => { +export const SearchInput: React.FC<{ className?: string; height?: string }> = ({ className, height = "h-12" }) => { const [searchParams] = useSearchParams(); const search = searchParams.get(EQueryParams.SEARCH_QUERY); const [searchQuery, setSearchQuery] = useState(search || EMPTY_STRING); @@ -22,7 +22,7 @@ export const SearchInput: React.FC<{ className?: string }> = ({ className }) => return (
[] => [ + { + accessorKey: "name", + header: () => ( +
+ + {t("portal.list.columns.name")} +
+ ), + cell: ({ row }) => { + const name = row.getValue("name") as string; + const id = row.original.id; + + return ( + e.stopPropagation()}> + {name} + + ); + }, + }, + { + accessorKey: "description", + header: () => t("portal.list.columns.description"), + cell: ({ row }) => { + const description = row.getValue("description") as string; + return

{description}

; + }, + }, + { + accessorKey: "owner", + header: () =>

{t("portal.list.columns.owner")}

, + cell: ({ row }) => { + const address = row.original.ownerAddress; + const id = row.original.id; + + return ( + + ); + }, + }, +]; diff --git a/explorer/src/interfaces/swr/enum.ts b/explorer/src/interfaces/swr/enum.ts index 842056f1..d3d8d96f 100644 --- a/explorer/src/interfaces/swr/enum.ts +++ b/explorer/src/interfaces/swr/enum.ts @@ -13,4 +13,5 @@ export enum SWRKeys { GET_PORTALS_BY_ISSUER = "getPortalsByIssuer", GET_PORTAL_BY_ID = "getPortalByID", GET_PORTAL_MODULE_LIST = "getPortalModuleList", + GET_PORTAL_LIST = "getPortalList", } diff --git a/explorer/src/pages/Home/components/Jumbotron/index.tsx b/explorer/src/pages/Home/components/Jumbotron/index.tsx index 5fa8330b..bc92afd0 100644 --- a/explorer/src/pages/Home/components/Jumbotron/index.tsx +++ b/explorer/src/pages/Home/components/Jumbotron/index.tsx @@ -1,5 +1,6 @@ import { t } from "i18next"; import { ArrowUpRight } from "lucide-react"; +import { Trans } from "react-i18next"; import { Button } from "@/components/Buttons"; import { EButtonType } from "@/components/Buttons/enum"; @@ -22,13 +23,17 @@ export const Jumbotron: React.FC = () => { handler={() => window.open(veraxLink, "_blank")} buttonType={EButtonType.PRIMARY_LIME} iconRight={} + height="h-10" />

- {t("home.exploreEcosystem")} + }} />

- + ); }; diff --git a/explorer/src/pages/Search/components/SearchModules/loadModuleList.ts b/explorer/src/pages/Search/components/SearchModules/loadModuleList.ts index d233c201..4d59bc42 100644 --- a/explorer/src/pages/Search/components/SearchModules/loadModuleList.ts +++ b/explorer/src/pages/Search/components/SearchModules/loadModuleList.ts @@ -8,10 +8,10 @@ export const loadModuleList = async (module: ModuleDataMapper, parsedString: Par const [listByName, listByDescription] = parsedString.nameOrDescription ? await Promise.all([ module.findBy(ITEMS_PER_PAGE_DEFAULT, undefined, { - name_starts_with: parsedString.nameOrDescription, + name_contains_nocase: parsedString.nameOrDescription, }), module.findBy(ITEMS_PER_PAGE_DEFAULT, undefined, { - description_starts_with: parsedString.nameOrDescription, + description_contains_nocase: parsedString.nameOrDescription, }), ]) : []; diff --git a/explorer/src/pages/Search/components/SearchPortals/index.tsx b/explorer/src/pages/Search/components/SearchPortals/index.tsx new file mode 100644 index 00000000..e6ccb4b3 --- /dev/null +++ b/explorer/src/pages/Search/components/SearchPortals/index.tsx @@ -0,0 +1,37 @@ +import { t } from "i18next"; +import useSWR from "swr"; + +import { DataTable } from "@/components/DataTable"; +import { columns } from "@/constants/columns/portal"; +import { SWRKeys } from "@/interfaces/swr/enum"; +import { useNetworkContext } from "@/providers/network-provider/context"; +import { APP_ROUTES } from "@/routes/constants"; + +import { loadPortalList } from "./loadPortalList"; +import { SearchComponentProps } from "../interfaces"; +import { SearchWrapper } from "../SearchWrapper"; + +export const SearchPortals: React.FC = ({ getSearchData, parsedString, search }) => { + const { + sdk: { portal }, + network: { chain }, + } = useNetworkContext(); + + const { data } = useSWR( + `${SWRKeys.GET_PORTAL_LIST}/${SWRKeys.SEARCH}/${search}/${chain.id}`, + async () => loadPortalList(portal, parsedString), + { + shouldRetryOnError: false, + revalidateAll: false, + onSuccess: (successData) => getSearchData(successData.length, true), + onError: () => getSearchData(0, true), + }, + ); + + if (!data || !data.length) return null; + return ( + + + + ); +}; diff --git a/explorer/src/pages/Search/components/SearchPortals/loadPortalList.ts b/explorer/src/pages/Search/components/SearchPortals/loadPortalList.ts new file mode 100644 index 00000000..67a5ff2a --- /dev/null +++ b/explorer/src/pages/Search/components/SearchPortals/loadPortalList.ts @@ -0,0 +1,26 @@ +import PortalDataMapper from "@verax-attestation-registry/verax-sdk/lib/types/src/dataMapper/PortalDataMapper"; + +import { ITEMS_PER_PAGE_DEFAULT } from "@/constants"; +import { ResultParseSearch } from "@/interfaces/components"; +import { isNotNullOrUndefined } from "@/utils"; + +export const loadPortalList = async (portal: PortalDataMapper, parsedString: Partial) => { + const [listByName, listByDescription] = parsedString.nameOrDescription + ? await Promise.all([ + portal.findBy(ITEMS_PER_PAGE_DEFAULT, undefined, { + name_contains_nocase: parsedString.nameOrDescription, + }), + portal.findBy(ITEMS_PER_PAGE_DEFAULT, undefined, { + description_contains_nocase: parsedString.nameOrDescription, + }), + ]) + : []; + + const listByIds = ( + parsedString.address ? await Promise.all(parsedString.address.map((id) => portal.findOneById(id))) : [] + ).filter(isNotNullOrUndefined); + + const result = [...(listByIds || []), ...(listByName || []), ...(listByDescription || [])]; + + return result; +}; diff --git a/explorer/src/pages/Search/components/SearchSchemas/loadSchemaList.ts b/explorer/src/pages/Search/components/SearchSchemas/loadSchemaList.ts index 013f21cc..df009631 100644 --- a/explorer/src/pages/Search/components/SearchSchemas/loadSchemaList.ts +++ b/explorer/src/pages/Search/components/SearchSchemas/loadSchemaList.ts @@ -8,10 +8,10 @@ export const loadSchemaList = async (schema: SchemaDataMapper, parsedString: Par const [listByName, listByDescription] = parsedString.nameOrDescription ? await Promise.all([ schema.findBy(ITEMS_PER_PAGE_DEFAULT, undefined, { - name_contains: parsedString.nameOrDescription, + name_contains_nocase: parsedString.nameOrDescription, }), schema.findBy(ITEMS_PER_PAGE_DEFAULT, undefined, { - description_contains: parsedString.nameOrDescription, + description_contains_nocase: parsedString.nameOrDescription, }), ]) : []; diff --git a/explorer/src/pages/Search/index.tsx b/explorer/src/pages/Search/index.tsx index 1075872c..dc807b78 100644 --- a/explorer/src/pages/Search/index.tsx +++ b/explorer/src/pages/Search/index.tsx @@ -12,6 +12,7 @@ import { parseSearch } from "@/utils/searchUtils"; import { SearchAttestations } from "./components/SearchAttestations"; import { SearchModules } from "./components/SearchModules"; +import { SearchPortals } from "./components/SearchPortals"; import { SearchSchemas } from "./components/SearchSchemas"; //todo: load more and loading for child @@ -61,6 +62,11 @@ export const Search = () => { parsedString={parsedString} getSearchData={(count, loaded) => updateSearchElement("module", count, loaded)} /> + updateSearchElement("portal", count, loaded)} + /> )}