change: change app navbar

- Updated navbar on app to include new links
- install react-menu package and convert CategoriesList to it
This commit is contained in:
MTG2000
2022-05-26 13:42:21 +03:00
parent f56e269148
commit c9cd63e11b
9 changed files with 236 additions and 139 deletions

14
package-lock.json generated
View File

@@ -16,7 +16,7 @@
"@reduxjs/toolkit": "^1.8.1",
"@remirror/pm": "^1.0.16",
"@remirror/react": "^1.0.34",
"@szhsin/react-menu": "^3.0.0",
"@szhsin/react-menu": "^3.0.2",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^13.5.0",
@@ -14707,9 +14707,9 @@
}
},
"node_modules/@szhsin/react-menu": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-3.0.0.tgz",
"integrity": "sha512-KLyIp6mqOLzDNnLVtYYy7m3IfjwVpJImqFaPbNY0oT2cScD559E8dG6jl7dzk2FBav/zjqXd54vzjyHZAB83yQ==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-3.0.2.tgz",
"integrity": "sha512-m9Ly+cT+CxQx3xhq90CVaOLQWU7f7UKeMxfDt1gPYV23tDwEe8Zo6PO547qPlAEGEwwb9MdA38U8OyueXKJc2g==",
"dependencies": {
"prop-types": "^15.7.2",
"react-transition-state": "^1.1.4"
@@ -77536,9 +77536,9 @@
}
},
"@szhsin/react-menu": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-3.0.0.tgz",
"integrity": "sha512-KLyIp6mqOLzDNnLVtYYy7m3IfjwVpJImqFaPbNY0oT2cScD559E8dG6jl7dzk2FBav/zjqXd54vzjyHZAB83yQ==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-3.0.2.tgz",
"integrity": "sha512-m9Ly+cT+CxQx3xhq90CVaOLQWU7f7UKeMxfDt1gPYV23tDwEe8Zo6PO547qPlAEGEwwb9MdA38U8OyueXKJc2g==",
"requires": {
"prop-types": "^15.7.2",
"react-transition-state": "^1.1.4"

View File

@@ -11,7 +11,7 @@
"@reduxjs/toolkit": "^1.8.1",
"@remirror/pm": "^1.0.16",
"@remirror/react": "^1.0.34",
"@szhsin/react-menu": "^3.0.0",
"@szhsin/react-menu": "^3.0.2",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^13.5.0",

View File

@@ -14,28 +14,35 @@ const items = [
{
heading: "What is BOLT.FUN ??",
content: <p className='text-body4 text-gray-600'>
Exercitation in fugiat est ut ad ea cupidatat ut in
cupidatat occaecat ut occaecat consequat est minim minim
esse tempor laborum consequat esse adipisicing eu
reprehenderit enim.
BOLT.FUN is a place by the community for the community of Lapps makers, developers, passionates, & anyone else interested.
</p>
},
{
heading: "What Do we do ??",
heading: "What can you do here ??",
content: <p className='text-body4 text-gray-600'>
Exercitation in fugiat est ut ad ea cupidatat ut in
cupidatat occaecat ut occaecat consequat est minim minim
esse tempor laborum consequat esse adipisicing eu
reprehenderit enim.
- Publish & view the various Lapps out there
<br />
- Read stories
<br />
- Ask/Answer questions
<br />
- Offer/Complete bounties
<br />
- View/Add hackathons
<br />
</p>
},
{
heading: "Who is working on BOLT.FUN ??",
content: <p className='text-body4 text-gray-600'>
Exercitation in fugiat est ut ad ea cupidatat ut in
cupidatat occaecat ut occaecat consequat est minim minim
esse tempor laborum consequat esse adipisicing eu
reprehenderit enim.
- Johns (Manager)
<br />
- Ed (Product Designer)
<br />
- Alexandare (Designer)
<br />
- MTG (Developer)
<br />
</p>
},
]

View File

@@ -1,40 +1,52 @@
import {
MenuItem,
} from '@szhsin/react-menu'
import Skeleton from 'react-loading-skeleton'
import { Link } from 'react-router-dom'
import { Link, useNavigate } from 'react-router-dom'
import { useNavCategoriesQuery } from 'src/graphql'
import { numberFormatter } from 'src/utils/helperFunctions'
interface Props {
// categories: Pick<ProjectCategory, 'id' | 'title' | 'icon' | 'votes_sum'>[]
classes?: Partial<{ list: string, item: string }>
classes?: Partial<{ item: string }>
onClick?: (categoryId: number) => void
}
;
export default function CategoriesList({ classes = {}, onClick }: Props) {
const { data, loading } = useNavCategoriesQuery()
const navigate = useNavigate()
if (loading)
return <ul className={classes.list}>
return <>
{Array(5).fill(0).map((_, idx) =>
<li key={idx} className={`flex p-16 text-body4 font-semibold items-center hover:bg-gray-100 rounded-8 ${classes.item}`} >
<span className="text-body3 mr-8"><Skeleton width='1.5ch' /></span> <Skeleton width='10ch' /> <span className="ml-auto text-body5 font-normal text-gray-400"><Skeleton width='2ch' /></span>
</li>
)}
</ul>
</>
return (
<ul className={classes.list}>
<>
{data?.allCategories.map(category =>
<Link
onClick={() => onClick?.(category.id)}
<MenuItem
className={`w-full !p-16 text-body4 font-semibold hover:bg-gray-100 !rounded-8 ${classes.item}`}
onClick={() => {
onClick?.(category.id)
navigate(`/category/${category.id}`)
}}
key={category.id}
to={`/category/${category.id}`}>
<li className={`flex p-16 text-body4 font-semibold items-center hover:bg-gray-100 rounded-8 ${classes.item}`} >
<span className="text-body3 mr-8">{category.icon}</span> {category.title} <span className="ml-auto text-body5 font-normal text-gray-400">{numberFormatter(category.votes_sum)}</span>
href={`/category/${category.id}`}
>
<li className={`flex w-items-center `} >
<span className="text-body3 mr-8">{category.icon}</span> {category.title} <span className="ml-auto pl-8 text-body5 font-normal text-gray-400">{numberFormatter(category.votes_sum)}</span>
</li>
</Link>)}
</ul>
</MenuItem>
)}
</>
)
}

View File

@@ -9,11 +9,23 @@ import Search from "./Search/Search";
import IconButton from "../IconButton/IconButton";
import { toggleSearch } from "src/redux/features/ui.slice";
import { navLinks } from "./Navbar";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import CategoriesList from "./CategoriesList/CategoriesList";
import { useEffect, useRef, useState } from "react";
import { IoExtensionPuzzle } from "react-icons/io5";
import { useClickOutside, useToggle } from "@react-hookz/web";
import {
Menu,
MenuItem,
MenuButton,
MenuDivider,
SubMenu
} from '@szhsin/react-menu';
import '@szhsin/react-menu/dist/index.css';
import { FiChevronDown, FiSend } from "react-icons/fi";
import { MdComment, MdOutlineExplore, MdOutlineLocalFireDepartment } from "react-icons/md";
import { IoMdTrophy } from "react-icons/io";
import { BiCoinStack } from "react-icons/bi";
export default function NavDesktop() {
@@ -51,6 +63,8 @@ export default function NavDesktop() {
);
};
const navigate = useNavigate()
return (<nav className="bg-white w-full flex fixed h-[118px] top-0 left-0 py-36 px-32 items-center z-[2010]">
<a href="https://bolt.fun/">
@@ -59,47 +73,82 @@ export default function NavDesktop() {
</h2>
</a>
<ul className="flex gap-32 xl:gap-64">
{navLinks.map((link, idx) => <li key={idx} className=" relative">
<Link to={link.url} className='text-body4 hover:text-primary-600'>
<link.icon className={`text-body2 inline-block mr-8 text-primary-600`} />
<span className="align-middle">{link.text}</span>
</Link>
<li>
<Menu offsetY={24} menuClassName='!rounded-12 !p-0' menuButton={<MenuButton className='text-body4 font-bold hover:text-primary-600'>LApps <FiChevronDown className="ml-8" /></MenuButton>}>
<MenuItem
href="/"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/");
}}
className='!px-24 !py-16 font-medium'
>
<MdOutlineExplore className={`text-body1 inline-block mr-12 text-primary-600 `} /> Explore
</MenuItem>
<MenuItem
href="/hottest"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/hottest");
}}
className='!px-24 !py-16 font-medium'
>
<MdOutlineLocalFireDepartment className={`text-body1 inline-block mr-12 text-primary-600 `} /> Hottest
</MenuItem>
<SubMenu
overflow="auto"
itemProps={{ className: '!p-0' }}
label={<div className='!px-24 !py-16 font-medium'><IoExtensionPuzzle className={`text-body1 inline-block mr-12 text-primary-600 `} /> Categories</div>}
>
<CategoriesList />
</SubMenu>
<MenuItem
href="https://airtable.com/shr2VkxarNsIFilDz"
target="_blank" rel="noopener noreferrer"
className='!px-24 !py-16 font-medium'
>
<FiSend className={`text-body1 inline-block mr-12 text-primary-600 `} /> Submit LApp
</MenuItem>
</Menu>
</li>
)}
<li
ref={categoriesRef}
className="relative"
>
<button
onClick={() => toggleCategories(!categoriesOpen)}
onKeyDown={e => (e.key !== 'Escape') || toggleCategories(false)}
className='text-body4 hover:text-primary-600 cursor-pointer'
<li>
<Menu offsetY={24} menuClassName='!rounded-12 !p-0' menuButton={<MenuButton className='text-body4 font-bold hover:text-primary-600'>Community <FiChevronDown className="ml-8" /></MenuButton>}>
<MenuItem
href="/blog"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/blog");
}}
className='!px-24 !py-16 font-medium'
>
<MdComment className={`text-body1 inline-block mr-12 text-primary-600 `} /> Stories
</MenuItem>
<MenuItem
href="/hackathons"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/hackathons");
}}
className='!px-24 !py-16 font-medium'
>
<IoMdTrophy className={`text-body1 inline-block mr-12 text-primary-600 `} /> Hackathons
</MenuItem>
</Menu>
</li>
<li className="relative">
<a
href={'https://bolt.fun/guide/'}
target="_blank"
rel="noreferrer"
className='text-body4 font-bold hover:text-primary-600'
>
<IoExtensionPuzzle className={`text-body2 inline-block mr-8 text-primary-600`} />
<span className="align-middle">Categories</span>
</button>
{<motion.div
initial={{ opacity: 0, y: 200, display: 'none' }}
animate={categoriesOpen ? {
opacity: 1, y: 16, display: 'initial',
transition: { ease: 'easeOut' }
} : {
opacity: [1, 0, 0],
y: [16, 40, 200],
transition: {
times: [0, .5, 1],
ease: "easeIn",
duration: .2
},
transitionEnd: {
display: 'none'
}
}}
className="absolute top-full left-0 w-[256px] bg-white border border-primary-50 rounded-8 shadow-3xl">
<CategoriesList onClick={() => toggleCategories(false)} />
</motion.div>}
Guide
</a>
</li>
<li className="relative">
<Link to={'/donate'} className='text-body4 font-bold hover:text-primary-600'>
Donate
</Link>
</li>
</ul>
@@ -109,7 +158,7 @@ export default function NavDesktop() {
className="flex"
>
<Button
{/* <Button
color="primary"
size="md"
className="lg:px-40"
@@ -117,7 +166,7 @@ export default function NavDesktop() {
newTab
>
Submit App
</Button>
</Button> */}
{/* {isWalletConnected ?
<Button className="ml-16 py-12 px-16 lg:px-20">Connected <AiFillThunderbolt className='inline-block text-thunder transform scale-125' /></Button>
: <Button className="ml-16 py-12 px-16 lg:px-20" onClick={onConnectWallet}><AiFillThunderbolt className='inline-block text-thunder transform scale-125' /> Connect Wallet </Button>
@@ -128,20 +177,6 @@ export default function NavDesktop() {
</IconButton>
</motion.div>
<Search />
{/* <form onBlur={toggleSearch} className='relative flex items-center' onSubmit={handleSubmit}>
{searchOpen ? <GrClose onClick={toggleSearch} className='text-gray-500 w-24 h-24 mx-12 z-20 hover:cursor-pointer' /> : <BsSearch onClick={toggleSearch} className='text-gray-500 w-24 h-24 mx-12 z-20 hover:cursor-pointer' />}
{searchOpen && <motion.input
ref={inputRef}
value={searchInput}
onChange={e => setSearchInput(e.target.value)}
initial={{ scaleX: .3, opacity: 0, originX: 'right' }}
animate={searchOpen ? { scaleX: 1, opacity: 1, originX: 'right' } : { scaleX: .3, opacity: 0, originX: 'right' }}
onAnimationComplete={() => {
if (searchOpen) inputRef.current?.focus()
}}
className="absolute top-0 right-0 z-10 bg-gray-100 text-gray-600 focus:outline-primary w-[300px] py-12 px-20 pr-40 rounded-24 placeholder-gray-500" placeholder="Search" />
}
</form> */}
</nav>
);

View File

@@ -1,5 +1,5 @@
import { motion } from "framer-motion";
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { BsChevronDown, BsSearch } from "react-icons/bs";
import { GrClose } from "react-icons/gr";
import Button from "../Button/Button";
@@ -8,13 +8,17 @@ import Search from "./Search/Search";
import IconButton from "../IconButton/IconButton";
import { useAppDispatch, useAppSelector } from "src/utils/hooks";
import { toggleSearch } from "src/redux/features/ui.slice";
import { FiMenu } from "react-icons/fi";
import { FiChevronDown, FiMenu, FiSend } from "react-icons/fi";
import { navLinks } from "./Navbar";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import { IoExtensionPuzzle } from "react-icons/io5";
import CategoriesList from "./CategoriesList/CategoriesList";
import { useToggle } from "@react-hookz/web";
import styles from './styles.module.css'
import { Menu, MenuButton, MenuItem, SubMenu } from "@szhsin/react-menu";
import '@szhsin/react-menu/dist/index.css';
import { IoMdTrophy } from "react-icons/io";
import { MdComment, MdOutlineExplore, MdOutlineLocalFireDepartment } from "react-icons/md";
interface Props {
}
@@ -58,6 +62,7 @@ const categoriesArrowVariants = {
export default function NavMobile({ }: Props) {
const dispatch = useAppDispatch();
const navigate = useNavigate()
const { searchOpen } = useAppSelector((state) => ({
isWalletConnected: state.wallet.isConnected,
searchOpen: state.ui.isSearchOpen
@@ -99,13 +104,6 @@ export default function NavMobile({ }: Props) {
animate={searchOpen ? { opacity: 0 } : { opacity: 1 }}
className="flex"
>
{/* <Button size="sm"
color="primary"
className="rounded-24"
href="https://airtable.com/shr2VkxarNsIFilDz"
newTab>
Submit App
</Button> */}
{/* <IconButton className='ml-8 self-center' onClick={handleSearchClick}>
<BsSearch className="text-gray-400" />
</IconButton> */}
@@ -132,15 +130,6 @@ export default function NavMobile({ }: Props) {
animate={drawerOpen ? "show" : "hide"}
>
<div className="flex flex-col gap-16 py-16">
{/* <form className='relative' onSubmit={handleSubmit}>
<BsSearch className='absolute top-1/2 left-20 transform -translate-x-1/2 -translate-y-1/2 text-gray-500' />
<input
value={searchInput}
onChange={e => setSearchInput(e.target.value)}
className="bg-gray-100 text-gray-600 focus:outline-primary w-full py-12 px-20 pl-40 rounded-24 placeholder-gray-500" placeholder="Search" />
<input className="btn bg-gray-100 w-full rounded-24 mt-16 placeholder-gray-500" placeholder="Search" />
</form> */}
<a
href="https://airtable.com/shr2VkxarNsIFilDz"
target="_blank"
@@ -151,7 +140,7 @@ export default function NavMobile({ }: Props) {
fullWidth
className="py-12 px-40 rounded-24 "
>
Submit App
Submit LApp
</Button>
</a>
@@ -167,33 +156,87 @@ export default function NavMobile({ }: Props) {
</Button>
{/* <Button color='gray' fullWidth className="py-12 px-40 rounded-24 my-16"> <AiFillThunderbolt className='inline-block text-thunder transform scale-125' /> Connect Wallet </Button> */}
</div>
<ul className="py-16 gap-64 border-t">
{navLinks.map((link, idx) => <li key={idx} className="text-body3 p-16 active:bg-gray-200">
<ul className="px-32 flex flex-col py-16 gap-32 border-t">
{/* {navLinks.map((link, idx) => <li key={idx} className="text-body3 p-16 active:bg-gray-200">
<Link to={link.url} onClick={() => toggleDrawerOpen(false)}><link.icon className={`text-body2 inline-block mr-12 text-primary-600`} /> <span className="align-middle">{link.text}</span> </Link></li>
)}
<li >
<p className="text-body3 flex items-center p-16 active:bg-gray-200 cursor-pointer"
onClick={() => toggleCategories(!categoriesOpen)}
)} */}
<li>
<Menu offsetY={24} menuClassName='!rounded-12 !p-0' menuButton={<MenuButton className='text-body4 font-bold hover:text-primary-600'>LApps <FiChevronDown className="ml-8" /></MenuButton>}>
<MenuItem
href="/"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/");
}}
className='!px-24 !py-16 font-medium'
>
<MdOutlineExplore className={`text-body1 inline-block mr-12 text-primary-600 `} /> Explore
</MenuItem>
<MenuItem
href="/hottest"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/hottest");
}}
className='!px-24 !py-16 font-medium'
>
<MdOutlineLocalFireDepartment className={`text-body1 inline-block mr-12 text-primary-600 `} /> Hottest
</MenuItem>
<SubMenu
itemProps={{ className: '!p-0' }}
direction='bottom'
overflow="auto"
label={<div className='!px-24 !py-16 font-medium'><IoExtensionPuzzle className={`text-body1 inline-block mr-12 text-primary-600 `} /> Categories</div>}
>
<CategoriesList />
</SubMenu>
<MenuItem
href="https://airtable.com/shr2VkxarNsIFilDz"
target="_blank" rel="noopener noreferrer"
className='!px-24 !py-16 font-medium'
>
<FiSend className={`text-body1 inline-block mr-12 text-primary-600 `} /> Submit LApp
</MenuItem>
</Menu>
</li>
<li>
<Menu offsetY={24} menuClassName='!rounded-12 !p-0' menuButton={<MenuButton className='text-body4 font-bold hover:text-primary-600'>Community <FiChevronDown className="ml-8" /></MenuButton>}>
<MenuItem
href="/blog"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/blog");
}}
className='!px-24 !py-16 font-medium'
>
<MdComment className={`text-body1 inline-block mr-12 text-primary-600 `} /> Stories
</MenuItem>
<MenuItem
href="/hackathons"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/hackathons");
}}
className='!px-24 !py-16 font-medium'
>
<IoMdTrophy className={`text-body1 inline-block mr-12 text-primary-600 `} /> Hackathons
</MenuItem>
</Menu>
</li>
<li className="relative">
<a
href={'https://bolt.fun/guide/'}
target="_blank"
rel="noreferrer"
className='text-body4 font-bold hover:text-primary-600'
>
<IoExtensionPuzzle className={`text-body2 inline-block mr-12 text-primary-600`} /> Categories
<motion.span
variants={categoriesArrowVariants}
initial={'closed'}
animate={categoriesOpen ? 'open' : 'closed'}
className="ml-auto">
<BsChevronDown className=" text-gray-400" />
</motion.span>
</p>
{<motion.div
variants={categoriesListVariants}
initial={'closed'}
animate={categoriesOpen ? 'open' : 'closed'}
>
<CategoriesList
classes={{ list: "pl-32" }}
onClick={() => toggleDrawerOpen(false)}
/>
</motion.div>}
Guide
</a>
</li>
<li className="relative">
<Link to={'/donate'} className='text-body4 font-bold hover:text-primary-600'>
Donate
</Link>
</li>
</ul>
<ul className="px-16 py-16 pb-32 flex flex-wrap gap-y-12 border-t pt-32 mt-auto">

View File

@@ -2,7 +2,7 @@ import { BiCoinStack } from "react-icons/bi";
import { FiGrid } from "react-icons/fi";
import { IoMedalOutline, IoRocketOutline } from "react-icons/io5";
import { useDonationsStatsQuery } from "src/graphql";
import { generateList } from "src/utils/helperFunctions";
import { generateList, numberFormatter } from "src/utils/helperFunctions";
import StatCard from "../StatCard/StatCard";
import StatCardSkeleton from "../StatCard/StatCard.Skeleton";
@@ -23,7 +23,7 @@ export default function DonationStats() {
<StatCard
color="#8B5CF6"
label={<><BiCoinStack className='w-full lg:w-auto scale-125 mr-8' /> <span className="align-middle">Donations</span></>}
value={donationsStatQuery.data?.getDonationsStats.donations}
value={<>{numberFormatter(Number(donationsStatQuery.data?.getDonationsStats.donations))} < span className="text-body4">Sats</span></>}
/>
<StatCard
color="#F59E0B"

View File

@@ -16,7 +16,7 @@ export default function StatCard(props: Props) {
<p className="text-body4">
{props.label}
</p>
<p className="text-h3 sm:text-h2 mt-8 font-bolder">
<p className="text-h4 sm:text-h2 mt-8 font-bolder whitespace-nowrap">
{props.value}
</p>
</div>

View File

@@ -181,7 +181,7 @@ export const handlers = [
ctx.data({
getDonationsStats: {
applications: '32',
donations: "$2.6k",
donations: '2600',
prizes: "$2.5k",
touranments: "1",
}