diff --git a/packages/web/components/MegaMenu/MegaMenu.tsx b/packages/web/components/MegaMenu/MegaMenu.tsx
new file mode 100644
index 00000000..9a73ffef
--- /dev/null
+++ b/packages/web/components/MegaMenu/MegaMenu.tsx
@@ -0,0 +1,565 @@
+import {
+ Avatar,
+ Box,
+ BoxedNextImage as Image,
+ Button,
+ ChevronDownIcon,
+ ChevronUpIcon,
+ CloseIcon,
+ Dashboard,
+ Flex,
+ HamburgerIcon,
+ Icon,
+ Link,
+ LogOut,
+ Menu,
+ MenuButton,
+ MenuItem,
+ MenuList,
+ MetaButton,
+ Profile,
+ SimpleGrid,
+ Spinner,
+ Stack,
+ Text,
+ useBreakpointValue,
+ useDisclosure,
+} from '@metafam/ds';
+import Alliances from 'assets/menuIcon/alliances.svg';
+import Asketh from 'assets/menuIcon/asketh.svg';
+import BecomeAPatron from 'assets/menuIcon/becomeapatron.svg';
+import Contribute from 'assets/menuIcon/contribute.svg';
+import Discord from 'assets/menuIcon/discord.svg';
+import Events from 'assets/menuIcon/events.svg';
+import Forum from 'assets/menuIcon/forum.svg';
+import Grants from 'assets/menuIcon/grants.svg';
+import Guilds from 'assets/menuIcon/guilds.svg';
+import Invest from 'assets/menuIcon/invest.svg';
+import Learn from 'assets/menuIcon/learn.svg';
+import MetaGameWiki from 'assets/menuIcon/metagamewiki.svg';
+import MetaRadio from 'assets/menuIcon/metaradio.svg';
+import Patrons from 'assets/menuIcon/patrons.svg';
+import Playbooks from 'assets/menuIcon/playbooks.svg';
+import Players from 'assets/menuIcon/players.svg';
+import Quests from 'assets/menuIcon/quests.svg';
+import Raids from 'assets/menuIcon/raids.svg';
+import Roles from 'assets/menuIcon/roles.svg';
+import SeedEarned from 'assets/menuIcon/seedearned.svg';
+import Seeds from 'assets/menuIcon/seeds.svg';
+import TheGreatHouses from 'assets/menuIcon/thegreathouses.svg';
+import WelcomeToMetaGame from 'assets/menuIcon/welcometometagame.svg';
+import XPEarned from 'assets/menuIcon/xpearned.svg';
+import Youtube from 'assets/menuIcon/youtube.svg';
+import { MetaLink } from 'components/Link';
+import { PlayerAvatar } from 'components/Player/PlayerAvatar';
+import { Player } from 'graphql/autogen/types';
+import { useUser, useWeb3 } from 'lib/hooks';
+import { useRouter } from 'next/router';
+import players from 'pages/community/players';
+import React from 'react';
+import { distinctUntilChanged, forkJoin, Subject } from 'rxjs';
+import { debounceTime, switchMap } from 'rxjs/operators';
+import { MenuLinkItem, MenuLinkSet, MenuSectionLinks } from 'utils/menuLinks';
+import { getPlayerURL } from 'utils/playerHelpers';
+
+import { getPlayersByText } from '../../graphql/getPlayers';
+import { getGuildsByText } from '../../graphql/queries/guild';
+import { XPSeedsBalance } from './XPSeedsBalance';
+
+const menuIcons: { [key: string]: string } = {
+ alliances: Alliances,
+ asketh: Asketh,
+ contribute: Contribute,
+ discord: Discord,
+ forum: Forum,
+ grants: Grants,
+ guilds: Guilds,
+ invest: Invest,
+ learn: Learn,
+ metagamewiki: MetaGameWiki,
+ patrons: Patrons,
+ playbooks: Playbooks,
+ players: Players,
+ quests: Quests,
+ raids: Raids,
+ roles: Roles,
+ seedearned: SeedEarned,
+ seeds: Seeds,
+ thegreathouses: TheGreatHouses,
+ welcometometagame: WelcomeToMetaGame,
+ xpearned: XPEarned,
+ youtube: Youtube,
+ metaradio: MetaRadio,
+ events: Events,
+ becomeapatron: BecomeAPatron,
+};
+
+type LogoProps = {
+ link: string;
+};
+
+const iconSize = 60;
+
+// Navbar logo
+const Logo = ({ link }: LogoProps) => {
+ const width = useBreakpointValue({ base: 36, lg: 40 }) ?? (36 as number);
+ const height =
+ useBreakpointValue({ base: 45, lg: iconSize }) ?? (45 as number);
+
+ return (
+
+
+
+
+
+ );
+};
+
+type MenuItemProps = {
+ title: string;
+ url: string;
+ explainerText: string;
+ icon: string;
+};
+// Menu links (with icons and explanatory text) -- used in DesktopNavLinks below
+const DesktopMenuItem = ({
+ title,
+ url,
+ explainerText,
+ icon,
+}: MenuItemProps) => (
+
+);
+
+// Nav links on desktop -- text and links from utils/menuLinks.ts
+const DesktopNavLinks = () => (
+
+ {MenuSectionLinks.map((section: MenuLinkSet) => (
+
+ ))}
+
+);
+
+// const getAllSearchResults = async (queryString: string) => {
+// const { players } = await getPlayersByText(queryString);
+// const { guilds } = await getGuildsByText(queryString);
+// return { players, guilds };
+// };
+
+// Search -- not working yet
+const Search = () => {
+ const searchInputSubjectRef = React.useRef(new Subject());
+ const [query, setQuery] = React.useState('');
+ const [searchResults, setSearchResults] = React.useState({
+ players: [],
+ guilds: [],
+ });
+ const [isLoading, setLoading] = React.useState(false);
+ const handleSubmit = (e: React.ChangeEvent) => {
+ e.preventDefault();
+ // Default Show Players Matching With Query
+ // router.push(`/search/players?q=${inputValue}`);
+ };
+ const handleChange = (e: any) => {
+ setQuery(e.target.value);
+ };
+
+ React.useEffect(() => {
+ setLoading(true);
+ searchInputSubjectRef.current.next(query);
+ }, [query]);
+
+ React.useEffect(() => {
+ const searchSubscription = searchInputSubjectRef.current
+ .pipe(
+ debounceTime(300),
+ distinctUntilChanged(),
+ // switchMap(async (queryString: string) => {
+ // if (queryString !== '' && !queryString) {
+ // setSearchResults([]);
+ // return;
+ // }
+ // const { players } = await getPlayersByText(queryString);
+ // const { guilds } = await getGuildsByText(queryString);
+ // // eslint-disable-next-line consistent-return
+ // return { players, guilds };
+ // }),
+ // switchMap((queryString: string) => {
+ // if (queryString !== '' && !queryString) {
+ // setSearchResults([]);
+ // return;
+ // }
+
+ // // eslint-disable-next-line consistent-return
+ // return forkJoin([
+ // getPlayersByText(queryString),
+ // getGuildsByText(queryString),
+ // ]);
+ // }),
+ )
+ .subscribe(async (val: string) => {
+ if (val !== '' && !val) {
+ setLoading(false);
+
+ return;
+ }
+ const { players } = await getPlayersByText(val);
+ const { guilds } = await getGuildsByText(val);
+ setSearchResults({ guilds, players });
+ setLoading(false);
+ });
+
+ return searchSubscription.unsubscribe;
+ }, []);
+ return (
+
+
+
+ );
+};
+
+const inputStyle = {
+ padding: '5px',
+};
+
+type PlayerStatsProps = {
+ player: Player;
+};
+// Display player XP and Seed
+const PlayerStats: React.FC = ({ player }) => {
+ const { disconnect } = useWeb3();
+
+ return (
+
+
+
+
+ );
+};
+
+export const MegaMenu: React.FC = () => {
+ const { connected, connect } = useWeb3();
+ const router = useRouter();
+ const { user, fetching } = useUser();
+ const { player } = user ?? {};
+
+ const { isOpen, onOpen, onClose } = useDisclosure();
+ const menuToggle = () => (isOpen ? onClose() : onOpen());
+
+ return (
+
+ );
+};
diff --git a/packages/web/graphql/getPlayers.ts b/packages/web/graphql/getPlayers.ts
index edd471d3..c5b6f5f7 100644
--- a/packages/web/graphql/getPlayers.ts
+++ b/packages/web/graphql/getPlayers.ts
@@ -11,11 +11,18 @@ import {
Order_By,
Player,
Player_Bool_Exp,
+ PlayerFragmentFragment,
+ SearchPlayersDocument,
+ SearchPlayersQuery,
+ SearchPlayersQueryVariables,
} from 'graphql/autogen/types';
import { client as defaultClient } from 'graphql/client';
import { PlayerFragment, PlayerSkillFragment } from 'graphql/fragments';
import { Client } from 'urql';
+import { client as defaultClient } from './client';
+import { PlayerFragment, PlayerSkillFragment } from './fragments';
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
/* GraphQL */ `
query GetPlayers(
@@ -193,3 +200,36 @@ export const getPlayerFilters = async (client: Client = defaultClient) => {
return data;
};
+
+// eslint-disable-next-line @typescript-eslint/no-unused-expressions
+/* GraphQL */ `
+ query SearchPlayers($search: String! ,$forLoginDisplay: Boolean! = false) {
+ player(where: { _or: [
+ { profile: { username: { _ilike: $search } } },
+ { ethereumAddress: { _ilike: $search } }
+ ] },limit:3) {
+ ...PlayerFragment
+}
+ ${PlayerFragment}
+}
+`;
+
+export const getPlayersByText = async (
+ text: string,
+ client: Client = defaultClient,
+) => {
+ const { data, error } = await client
+ .query(
+ SearchPlayersDocument,
+ {
+ search: `%${text}%`,
+ },
+ )
+ .toPromise();
+
+ return {
+ players: data?.player || [],
+ // count: data?.player_aggregate.aggregate?.count || 0,
+ error,
+ };
+};
diff --git a/packages/web/graphql/queries/guild.ts b/packages/web/graphql/queries/guild.ts
index 49703896..c5d2afd0 100644
--- a/packages/web/graphql/queries/guild.ts
+++ b/packages/web/graphql/queries/guild.ts
@@ -7,6 +7,9 @@ import {
GetGuildPlayersQueryVariables,
GetGuildQuery,
GetGuildQueryVariables,
+ GetGuildsByTextSearchDocument,
+ GetGuildsByTextSearchQuery,
+ GetGuildsByTextSearchQueryVariables,
GetGuildsQuery,
GetGuildsQueryVariables,
GuildFragment as GuildFragmentType,
@@ -160,3 +163,29 @@ export const getGuildPlayers = async (
return guildPlayers;
};
+
+// eslint-disable-next-line @typescript-eslint/no-unused-expressions
+/* GraphQL */ `
+ query getGuildsByTextSearch($text: String) {
+ search_guilds(args: { search: $text }, limit: 3) {
+ ...GuildFragment
+ }
+ }
+ ${GuildFragment}
+`;
+
+export const getGuildsByText = async (text: string) => {
+ const { data, error } = await client
+ .query(
+ GetGuildsByTextSearchDocument,
+ {
+ text: `%${text}%`,
+ },
+ )
+ .toPromise();
+
+ return {
+ guilds: data?.search_guilds || [],
+ error,
+ };
+};
diff --git a/packages/web/package.json b/packages/web/package.json
index 1b98926e..3e704704 100644
--- a/packages/web/package.json
+++ b/packages/web/package.json
@@ -63,6 +63,7 @@
"react-resizable": "3.0.4",
"react-vis": "1.11.7",
"rss-to-json": "2.0.2",
+ "rxjs": "7.5.3",
"sourcecred": "0.9.0",
"swr": "1.0.1",
"urql": "2.0.2",