fix: fix some QA issues

- fix navbar height
- remove input shadow
- change donateCard options style
- add 2px borders to cards
- remove search from nav on sections other than products
- implement useMediaQuery
This commit is contained in:
MTG2000
2022-05-26 20:27:39 +03:00
parent 5c7723316b
commit 113ec18479
18 changed files with 150 additions and 120 deletions

View File

@@ -3,7 +3,7 @@ import Navbar from "src/Components/Navbar/Navbar";
import ModalsContainer from "src/Components/Modals/ModalsContainer/ModalsContainer";
import { useAppSelector } from './utils/hooks';
import { Wallet_Service } from "./services";
import { Route, Routes } from "react-router-dom";
import { Navigate, Route, Routes } from "react-router-dom";
import { useWrapperSetup } from "./utils/Wrapper";
import LoadingPage from "./Components/LoadingPage/LoadingPage";
@@ -45,13 +45,18 @@ function App() {
<Navbar />
<Suspense fallback={<LoadingPage />}>
<Routes>
<Route path="/hottest" element={<HottestPage />} />
<Route path="/category/:id" element={<CategoryPage />} />
<Route path="/products/hottest" element={<HottestPage />} />
<Route path="/products/category/:id" element={<CategoryPage />} />
<Route path="/products" element={<ExplorePage />} />
<Route path="/blog/post/:type/:id" element={<PostDetailsPage />} />
<Route path="/blog" element={<FeedPage />} />
<Route path="/hackathons" element={<HackathonsPage />} />
<Route path="/donate" element={<DonatePage />} />
<Route path="/" element={<ExplorePage />} />
<Route path="/" element={<Navigate to="/products" />} />
</Routes>
</Suspense>
<ModalsContainer />

View File

@@ -33,13 +33,14 @@ export default function CategoriesList({ classes = {}, onClick }: Props) {
<>
{data?.allCategories.map(category =>
<MenuItem
className={`w-full !p-16 text-body4 font-semibold hover:bg-gray-100 !rounded-8 flex w-items-center ${classes.item}`}
onClick={() => {
onClick?.(category.id)
navigate(`/category/${category.id}`)
}}
key={category.id}
href={`/category/${category.id}`}
className={`w-full !p-16 text-body4 font-semibold hover:bg-gray-100 !rounded-8 flex w-items-center ${classes.item}`}
href={`/products/category/${category.id}`}
onClick={(e) => {
e.syntheticEvent.preventDefault();
onClick?.(category.id)
navigate(`/products/category/${category.id}`)
}}
>
<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>
</MenuItem>

View File

@@ -1,7 +1,7 @@
import { BsSearch } from "react-icons/bs";
import { motion } from "framer-motion";
import { useAppDispatch, useAppSelector } from "src/utils/hooks";
import { useAppDispatch, useAppSelector, useCurrentSection } from "src/utils/hooks";
import { openModal } from "src/redux/features/modals.slice";
import Button from "../Button/Button";
import ASSETS from "src/assets";
@@ -46,27 +46,11 @@ export default function NavDesktop() {
};
const onConnectWallet = () => {
dispatch(
openModal({
Modal: "Login_ScanningWalletCard",
})
);
};
const onWithdraw = () => {
dispatch(
openModal({
Modal: "Claim_FundWithdrawCard",
})
);
};
const currentSection = useCurrentSection();
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]">
return (<nav className="bg-white w-full flex fixed h-[72px] top-0 left-0 py-36 px-32 items-center z-[2010]">
<a href="https://bolt.fun/">
<h2 className="text-h5 font-bold mr-40 lg:mr-64">
<img className='h-40' src={ASSETS.Logo} alt="Bolt fun logo" />
@@ -76,20 +60,20 @@ export default function NavDesktop() {
<li>
<Menu offsetY={24} menuClassName='!rounded-12' menuButton={<MenuButton className='text-body4 font-bold hover:text-primary-600'>LApps <FiChevronDown className="ml-8" /></MenuButton>}>
<MenuItem
href="/"
href="/products"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/");
navigate("/products");
}}
className='!px-24 !py-16 font-medium'
>
<MdOutlineExplore className={`text-body1 inline-block mr-12 text-primary-600 `} /> Explore
</MenuItem>
<MenuItem
href="/hottest"
href="/products/hottest"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/hottest");
navigate("/products/hottest");
}}
className='!px-24 !py-16 font-medium'
>
@@ -172,9 +156,9 @@ export default function NavDesktop() {
: <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>
} */}
<IconButton className='ml-16 self-center' onClick={handleSearchClick}>
{currentSection === 'products' && <IconButton className='ml-16 self-center' onClick={handleSearchClick}>
<BsSearch className='scale-125 text-gray-400' />
</IconButton>
</IconButton>}
</motion.div>
<Search />

View File

@@ -163,20 +163,20 @@ export default function NavMobile({ }: Props) {
<li>
<Menu offsetY={24} menuClassName='!rounded-12' menuButton={<MenuButton className='text-body4 font-bold hover:text-primary-600'>LApps <FiChevronDown className="ml-8" /></MenuButton>}>
<MenuItem
href="/"
href="/products"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/");
navigate("/products");
}}
className='!px-24 !py-16 font-medium'
>
<MdOutlineExplore className={`text-body1 inline-block mr-12 text-primary-600 `} /> Explore
</MenuItem>
<MenuItem
href="/hottest"
href="/products/hottest"
onClick={(e) => {
e.syntheticEvent.preventDefault();
navigate("/hottest");
navigate("/products/hottest");
}}
className='!px-24 !py-16 font-medium'
>

View File

@@ -1,14 +1,14 @@
import NavMobile from "./NavMobile";
import { MdComment, MdHomeFilled, MdLocalFireDepartment } from "react-icons/md";
import { IoExtensionPuzzle } from "react-icons/io5";
import { useCallback, useEffect } from "react";
import { useAppDispatch, useAppSelector } from "src/utils/hooks";
import { useCallback, useEffect, useState } from "react";
import { useAppDispatch, useAppSelector, useMediaQuery } from "src/utils/hooks";
import { openModal } from "src/redux/features/modals.slice";
import { setNavHeight } from "src/redux/features/ui.slice";
import NavDesktop from "./NavDesktop";
import { useMediaQuery } from "@react-hookz/web";
import { MEDIA_QUERIES } from "src/utils/theme/media_queries";
import { IoMdTrophy } from "react-icons/io";
import { useLocation } from "react-router-dom";
export const navLinks = [
@@ -39,34 +39,18 @@ export const navLinks = [
// },
];
export default function Navbar() {
const dispatch = useAppDispatch();
const { isWalletConnected, isMobileScreen } = useAppSelector((state) => ({
isWalletConnected: state.wallet.isConnected,
isMobileScreen: state.ui.isMobileScreen
}));
// const { isWalletConnected, isMobileScreen } = useAppSelector((state) => ({
// isWalletConnected: state.wallet.isConnected,
// isMobileScreen: state.ui.isMobileScreen
// }));
const isLargeScreen = useMediaQuery(MEDIA_QUERIES.isLarge)
const onConnectWallet = () => {
dispatch(
openModal({
Modal: "Login_ScanningWalletCard",
})
);
};
const onWithdraw = () => {
dispatch(
openModal({
Modal: "Claim_FundWithdrawCard",
})
);
};
useEffect(() => {
const nav = document.querySelector("nav");
@@ -84,17 +68,15 @@ export default function Navbar() {
document.body.style.paddingTop = oldPadding
}
}, [dispatch, isMobileScreen, isLargeScreen])
}, [dispatch])
return (
<>
{(isMobileScreen || !isLargeScreen) ?
<NavMobile />
:
{(isLargeScreen) ?
<NavDesktop />
:
<NavMobile />
}
</>
);

View File

@@ -15,18 +15,15 @@ const defaultOptions = [
export default function DonateCard() {
const size = useWindowSize();
const [selectedOption, setSelectedOption] = useState(-1);
const [donationAmount, setDonationAmount] = useState<number>();
const { donate, paymentStatus, isLoading } = useDonate()
const onChangeInput = (event: React.ChangeEvent<HTMLInputElement>) => {
setSelectedOption(-1);
setDonationAmount(Number(event.target.value));
};
const onSelectOption = (idx: number) => {
setSelectedOption(idx);
setDonationAmount(defaultOptions[idx].value);
}
@@ -37,13 +34,11 @@ export default function DonateCard() {
onSuccess: () => {
setTimeout(() => {
setDonationAmount(undefined);
setSelectedOption(-1);
}, 4000);
},
onError: () => {
setTimeout(() => {
setDonationAmount(undefined);
setSelectedOption(-1);
}, 4000);
}
});
@@ -60,7 +55,7 @@ export default function DonateCard() {
className={`input-text input-removed-arrows`}
value={donationAmount} onChange={onChangeInput}
type="number"
placeholder="1,000"
placeholder="Select or enter amount"
autoFocus
/>
<p className='px-16 shrink-0 self-center text-primary-400'>
@@ -72,7 +67,7 @@ export default function DonateCard() {
<button
type='button'
key={idx}
className={`btn border px-12 rounded-md py-8 text-body5 bg-primary-100 hover:bg-primary-50 text-primary-600 ${idx === selectedOption && "border-primary-500 bg-primary-100 hover:bg-primary-100 text-primary-600"}`}
className={`btn border-0 px-12 rounded-md py-8 text-body5 bg-primary-50 hover:bg-primary-100 outline-2 outline-primary-200 active:outline `}
onClick={() => onSelectOption(idx)}
>
{option.text}

View File

@@ -6,7 +6,7 @@ export default function DonatePage() {
return (
<div
className={`w-full`}
className={`w-full bg-white`}
>
<Header />
<div className={`${styles.faq}`}>

View File

@@ -14,7 +14,7 @@ interface Props {
export default function HackathonCard({ hackathon }: Props) {
return (
<div className="rounded-16 bg-white overflow-hidden">
<div className="rounded-16 bg-white overflow-hidden border-2">
<img className="w-full h-[120px] object-cover" src={hackathon.cover_image} alt="" />
<div className="p-16">
<div className="flex flex-col gap-8">

View File

@@ -22,7 +22,7 @@ interface Props {
export default function SortByFilter({ filterChanged }: Props) {
const [selected, setSelected] = useState<string | null>(null);
const [selected, setSelected] = useState<string | null>('Upcoming');
const filterClicked = (_newValue: string | null) => {
const newValue = selected !== _newValue ? _newValue : null;
@@ -37,7 +37,7 @@ export default function SortByFilter({ filterChanged }: Props) {
<>
{
isMdScreen ?
<div className='bg-white border rounded-12 p-16'>
<div className='bg-white border-2 rounded-12 p-16'>
< p className="text-body2 font-bolder text-black mb-16" > Sort By</p >
<ul>
{filters.map((f, idx) => <li

View File

@@ -29,7 +29,7 @@ export default function PopularTopicsFilter({ filterChanged }: Props) {
return (
<>
{isMdScreen ?
<div className='bg-white border rounded-12 p-16'>
<div className='bg-white border-2 rounded-12 p-16'>
<p className="text-body2 font-bolder text-black mb-16">Topics</p>
<ul className=' flex flex-col gap-16'>
{topicsQuery.loading ?

View File

@@ -26,7 +26,7 @@ export default function HackathonsPage() {
return (
<div
className={`page-container pt-16 w-full ${styles.grid}`}
className={`page-container pt-16 w-full ${styles.grid}`}
>
<aside className='no-scrollbar'>
<div className="sticky flex flex-col gap-24 md:overflow-y-scroll"

View File

@@ -1,11 +1,11 @@
.grid {
display: grid;
grid-template-columns: 100%;
gap: 32px;
gap: 24px;
@media screen and (min-width: 768px) {
grid-template-columns: 1fr 2fr 0;
gap: 32px;
gap: 24px;
}
@media screen and (min-width: 1024px) {

View File

@@ -28,7 +28,7 @@ export default function PopularTopicsFilter({ filterChanged }: Props) {
return (
<>
{isMdScreen ?
<div className='bg-white border rounded-12 p-16'>
<div className='bg-white border-2 rounded-12 p-16'>
<p className="text-body2 font-bolder text-black mb-16">Topics</p>
<ul className=' flex flex-col gap-16'>
{topicsQuery.loading ?

View File

@@ -40,7 +40,7 @@ export default function SortBy({ filterChanged }: Props) {
<>
{
isMdScreen ?
<div className='bg-white border rounded-12 p-16'>
<div className='bg-white border-2 rounded-12 p-16'>
< p className="text-body2 font-bolder text-black mb-16" > Sort By</p >
<ul>
{filters.map((f, idx) => <li

View File

@@ -3,47 +3,47 @@
@tailwind utilities;
@layer components {
.btn {
@apply text-gray-900 py-12 px-42 bg-gray-25 hover:bg-gray-50 font-sans rounded-lg font-regular border border-gray-300;
}
.btn {
@apply text-gray-900 py-12 px-42 bg-gray-25 hover:bg-gray-50 font-sans rounded-lg font-regular border border-gray-300;
}
.btn-primary {
@apply bg-primary-500 border-0 shadow-sm hover:bg-primary-400 text-white;
}
.btn-primary {
@apply bg-primary-500 border-0 shadow-sm hover:bg-primary-400 text-white;
}
.btn-gray {
@apply bg-gray-100 hover:bg-gray-200 text-gray-900;
}
.btn-gray {
@apply bg-gray-100 hover:bg-gray-200 text-gray-900;
}
.input-wrapper {
@apply relative w-full border border-gray-300 rounded-lg shadow-xs flex focus-within:outline-primary-400 focus-within:border-primary-300 focus-within:ring focus-within:ring-primary-200 focus-within:ring-opacity-50;
}
.input-wrapper {
@apply relative w-full border border-gray-300 rounded-lg flex focus-within:outline-primary-400 focus-within:border-primary-300 focus-within:ring focus-within:ring-primary-200 focus-within:ring-opacity-50;
}
.input-text {
@apply flex-grow border-none focus:border-0 focus:ring-0 bg-transparent min-w-0 text-primary-500;
}
.input-text {
@apply flex-grow border-none focus:border-0 focus:ring-0 bg-transparent min-w-0 text-primary-500;
}
.input-checkbox {
@apply rounded-4 bg-gray-200 border-transparent focus:border-transparent focus:bg-primary-200 text-primary-700 focus:ring-1 focus:ring-offset-2 focus:ring-primary-500;
}
.input-checkbox {
@apply rounded-4 bg-gray-200 border-transparent focus:border-transparent focus:bg-primary-200 text-primary-700 focus:ring-1 focus:ring-offset-2 focus:ring-primary-500;
}
.input-icon {
@apply h-full text-primary-500 flex-shrink-0 w-42 px-12 self-center;
}
.input-icon {
@apply h-full text-primary-500 flex-shrink-0 w-42 px-12 self-center;
}
.input-error {
@apply text-body6 text-red-500 mt-4;
}
.input-error {
@apply text-body6 text-red-500 mt-4;
}
.chip {
@apply bg-gray-100 text-body4 px-16 py-8 rounded-24 font-regular;
}
.chip {
@apply bg-gray-100 text-body4 px-16 py-8 rounded-24 font-regular;
}
.chip-small {
@apply bg-gray-100 text-body5 px-12 py-8 rounded-16 font-regular;
}
.chip-small {
@apply bg-gray-100 text-body5 px-12 py-8 rounded-16 font-regular;
}
.modal-card {
@apply rounded-[40px] bg-gray-50 overflow-hidden w-full shadow-2xl z-10;
}
}
.modal-card {
@apply rounded-[40px] bg-gray-50 overflow-hidden w-full shadow-2xl z-10;
}
}

View File

@@ -7,3 +7,5 @@ export * from "./useAutoResizableTextArea";
export * from "./useCopyToClipboard";
export * from "./useVote";
export * from './useWindowSize'
export * from './useMediaQuery'
export * from './useCurrentSection'

View File

@@ -0,0 +1,18 @@
import { useLocation } from "react-router-dom"
export const useCurrentSection = () => {
const location = useLocation();
if (location.pathname.startsWith('/blog'))
return 'blog';
if (location.pathname.startsWith('/hackathons'))
return 'hackathons';
if (location.pathname.startsWith('/products'))
return 'products';
if (location.pathname.startsWith('/donate'))
return 'donate';
return 'other'
}

View File

@@ -0,0 +1,43 @@
import { useEffect, useState } from 'react'
export function useMediaQuery(query: string): boolean {
const getMatches = (query: string): boolean => {
// Prevents SSR issues
if (typeof window !== 'undefined') {
return window.matchMedia(query).matches
}
return false
}
const [matches, setMatches] = useState<boolean>(getMatches(query))
function handleChange() {
setMatches(getMatches(query))
}
useEffect(() => {
const matchMedia = window.matchMedia(query)
// Triggered at the first client-side load and if query changes
handleChange()
// Listen matchMedia
if (matchMedia.addListener) {
matchMedia.addListener(handleChange)
} else {
matchMedia.addEventListener('change', handleChange)
}
return () => {
if (matchMedia.removeListener) {
matchMedia.removeListener(handleChange)
} else {
matchMedia.removeEventListener('change', handleChange)
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [query])
return matches
}