Skip to content

Commit

Permalink
Merge pull request #1974 from zeitgeistpm/staging
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] authored Nov 13, 2023
2 parents c283ddf + 1b0783b commit 79f1401
Show file tree
Hide file tree
Showing 6 changed files with 274 additions and 13 deletions.
2 changes: 1 addition & 1 deletion components/account/AccountButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const HeaderActionButton: FC<
> = ({ onClick, disabled, children }) => {
return (
<button
className={`flex border-2 rounded-full px-6 leading-[40px] text-white font-medium items-center border-white justify-center cursor-pointer disabled:cursor-default disabled:opacity-30`}
className={`w-[185px] flex border-2 rounded-full px-6 leading-[40px] text-white font-medium items-center border-white justify-center cursor-pointer disabled:cursor-default disabled:opacity-30`}
onClick={onClick}
disabled={disabled}
>
Expand Down
108 changes: 108 additions & 0 deletions components/markets/MarketSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { MarketStatus } from "@zeitgeistpm/indexer";
import { useMarketSearch } from "lib/hooks/queries/useMarketSearch";
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { Search, X } from "react-feather";

const MarketSearch = () => {
const [searchTerm, setSearchTerm] = useState("");
const [showResults, setShowResults] = useState(false);
const [showSearch, setShowSearch] = useState(false);
const wrapperRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);

const { data: markets } = useMarketSearch(searchTerm);
useEffect(() => {
const handleClickOutside = (event) => {
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
setShowResults(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [wrapperRef]);

return (
<div className="w-full mx-3 md:mx-7" ref={wrapperRef}>
<Link href={"/search"} className="w-2 lg:hidden">
<Search className="text-ztg-blue mr-4" />
</Link>
<div className="hidden lg:flex items-center">
<button
onClick={() => {
setShowSearch(true);
setTimeout(() => {
inputRef.current?.focus();
});
}}
>
<Search className="text-ztg-blue mr-4" />
</button>
{showSearch && (
<>
<input
ref={inputRef}
className="rounded-sm bg-sky-900 text-white h-8 px-2 w-full focus:outline-none max-w-[500px] "
value={searchTerm}
placeholder="Search markets"
onChange={(event) => {
setShowResults(true);
setSearchTerm(event.target.value);
}}
onFocus={() => {
setShowResults(true);
}}
/>
<button
className="relative right-6 text-sky-600"
onClick={() => {
setSearchTerm("");
inputRef.current?.focus();
}}
>
<X size={16} />
</button>
</>
)}
</div>
{showResults && markets && (
<div className="hidden lg:flex flex-col absolute bg-white py-2 rounded-md top-[45px] translate-x-[40px] max-h-[300px] overflow-scroll w-[500px] shadow-2xl">
<div className="text-sky-600 mx-4">Results</div>

{markets.length > 0 ? (
markets?.map((market) => (
<Link
href={`/markets/${market.marketId}`}
className="px-4 py-2 flex justify-between overflow-ellipsis hover:bg-sky-100"
onClick={() => {
setShowResults(false);
}}
>
<div className="overflow-ellipsis line-clamp-1 w-85%">
{market.question}
</div>
<div
className={`text-xs rounded-md px-2 py-1 w-16 text-center text-white ${
market.status === MarketStatus.Active
? "bg-sheen-green"
: "bg-vermilion"
}`}
>
{market.status === MarketStatus.Active
? "Active"
: "Inactive"}
</div>
</Link>
))
) : (
<div className="text-center w-full pt-6 pb-4">No results</div>
)}
</div>
)}
</div>
);
};

export default MarketSearch;
16 changes: 9 additions & 7 deletions components/top-bar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
FiList,
} from "react-icons/fi";
import { useCategoryCounts } from "lib/hooks/queries/useCategoryCounts";
import MarketSearch from "components/markets/MarketSearch";
import { Alerts } from "./Alerts";
import Modal from "components/ui/Modal";
import { DesktopOnboardingModal } from "components/account/OnboardingModal";
Expand Down Expand Up @@ -49,13 +50,13 @@ const TopBar = () => {
<div
className={`w-full py-3.5 fixed top-0 z-40 transition-all duration-300 bg-black h-topbar-height`}
>
<div className="h-full relative flex items-center container-fluid">
<div className="h-full hidden md:flex items-center justify-center border-r-1 border-blue-600 pr-3 md:pr-7">
<div className="h-full relative flex items-center px-4">
<div className="h-full hidden md:flex items-center justify-center pr-3 md:pr-7">
<Link href="/">
<MenuLogo />
</Link>
</div>
<div className="md:pl-7 flex flex-1 gap-7">
<div className="md:px-7 flex gap-7 items-center border-x-0 md:border-x-1 border-ztg-blue py-2">
<Menu as="div" className="relative inline-block text-left">
{({ open, close }) => {
return (
Expand Down Expand Up @@ -197,7 +198,8 @@ const TopBar = () => {
<div>Leaderboard</div>
</Link>
</div>
<div className="relative center gap-3">
<MarketSearch />
<div className="ml-auto relative center gap-3">
<GetTokensButton />
<AccountButton />
<Alerts />
Expand All @@ -223,7 +225,7 @@ const GetTokensButton = () => {
leaveTo="opacity-0 scale-90"
>
<Link
className="relative h-11 rounded-md p-0.5 overflow-hidden group"
className="relative h-11 rounded-md p-0.5 overflow-hidden group hidden sm:block"
href="/deposit"
>
<div
Expand All @@ -233,8 +235,8 @@ const GetTokensButton = () => {
"linear-gradient(180deg, #FF00E6 0%, #F36464 50%, #04C3FF 100%)",
}}
/>
<div className="relative h-full block z-20">
<button className="h-full w-full rounded-md px-3 md:px-5 bg-black text-white center">
<div className="relative h-full block z-20 sm:w-[125px] ">
<button className="h-full w-full rounded-md bg-black text-white center">
Get Tokens
</button>
</div>
Expand Down
14 changes: 9 additions & 5 deletions components/ui/QuillViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ const QuillViewer = ({ value }: { value: string }) => {
for (const match of matches) {
const [fullLink, linkText] = match;

const newLinkText =
linkText.length > maxLength
? linkText.substring(0, maxLength) + "..."
: linkText;
const linkContainSpaces = linkText.includes(" ");

value = value.replace(`>${linkText}<`, `>${newLinkText}<`);
if (linkContainSpaces === false) {
const newLinkText =
linkText.length > maxLength
? linkText.substring(0, maxLength) + "..."
: linkText;

value = value.replace(`>${linkText}<`, `>${newLinkText}<`);
}
}
return value;
}, [value]);
Expand Down
79 changes: 79 additions & 0 deletions lib/hooks/queries/useMarketSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useQuery } from "@tanstack/react-query";
import { isIndexedSdk } from "@zeitgeistpm/sdk";
import Fuse from "fuse.js";
import { useDebounce } from "use-debounce";
import { useSdkv2 } from "../useSdkv2";
import { MarketOrderByInput } from "@zeitgeistpm/indexer";

export const marketSearchKey = "market-search";

export const useMarketSearch = (searchTerm: string) => {
const [sdk, id] = useSdkv2();

const [debouncedSearchTerm] = useDebounce(searchTerm, 300);

const enabled =
isIndexedSdk(sdk) && debouncedSearchTerm && debouncedSearchTerm.length > 1;

const query = useQuery(
[id, marketSearchKey, debouncedSearchTerm],
async () => {
if (enabled) {
const search = buildSearch(debouncedSearchTerm);
const { markets } = await sdk.indexer.markets({
where: {
OR: search,
},
order: MarketOrderByInput.IdDesc,
limit: 100,
});

const fuse = new Fuse(markets, {
includeScore: true,
threshold: 0.9,
keys: [
//matches in the question are consisdered more important than description, slightly favour active markets
{
name: "question",
weight: 3,
},
{
name: "description",
weight: 1,
},
{ name: "status", weight: 0.2 },
],
});

const result = fuse.search({
$or: [
{ question: debouncedSearchTerm },
{ description: debouncedSearchTerm },
{ status: "Active" },
],
});

return result.map((r) => r.item);
}
},
{
enabled: Boolean(enabled),
staleTime: 10_000,
},
);

return query;
};

const buildSearch = (searchTerm: string) => {
const search = searchTerm
.trim()
.split(" ")
.map((word) => [
{ question_containsInsensitive: word },
{ description_containsInsensitive: word },
])
.flat();

return search;
};
68 changes: 68 additions & 0 deletions pages/search.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { MarketStatus } from "@zeitgeistpm/indexer";
import { useMarketSearch } from "lib/hooks/queries/useMarketSearch";
import { NextPage } from "next";
import Link from "next/link";
import { useState } from "react";
import { X } from "react-feather";

const SearchPage: NextPage = () => {
const [searchTerm, setSearchTerm] = useState("");

const { data: markets } = useMarketSearch(searchTerm);
return (
<div className="mt-4">
<div className="flex items-center px-2">
<input
className="rounded-md h-8 px-2 w-full focus:outline-none max-w-[500px] border border-sky-200"
value={searchTerm}
placeholder="Search markets"
onChange={(event) => {
setSearchTerm(event.target.value);
}}
/>
<button
className="relative right-6 text-sky-600"
onClick={() => {
setSearchTerm("");
}}
>
<X size={16} />
</button>
</div>
{markets && (
<div className="flex flex-col py-4">
<div className="text-sky-600 px-2">Results</div>

{markets.length > 0 ? (
markets?.map((market) => (
<Link
href={`/markets/${market.marketId}`}
className="py-2 flex overflow-ellipsis hover:bg-sky-100 px-2 rounded-md"
>
<div className="overflow-ellipsis line-clamp-1 mr-4">
{market.question}
</div>
<div
className={`ml-auto text-xs rounded-md px-2 py-1 w-16 text-center text-white ${
market.status === MarketStatus.Active
? "bg-sheen-green"
: "bg-vermilion"
}`}
>
{market.status === MarketStatus.Active
? "Active"
: "Inactive"}
</div>
</Link>
))
) : (
<div className="w-full pt-6 pb-4">No results</div>
)}
{}
</div>
)}
</div>
);
};

export default SearchPage;

0 comments on commit 79f1401

Please sign in to comment.