From 6e7c18ced6b87dab63c322c102050e4f2b0a8f6e Mon Sep 17 00:00:00 2001 From: veeso Date: Tue, 10 Dec 2024 15:09:43 +0100 Subject: [PATCH] fix: guide --- package.json | 18 +- sitemap.xml | 5 + src/js/components/App/Routes.tsx | 67 +- src/js/components/App/pages/About/Team.tsx | 2 +- src/js/components/App/pages/Guide/MdPage.tsx | 127 ++ src/js/components/App/pages/Guide/Wrapper.tsx | 106 +- .../App/pages/Guide/pages/Architecture.tsx | 14 + .../App/pages/Guide/pages/Deferred.tsx | 14 + .../App/pages/Guide/pages/DeferredData.tsx | 14 + .../App/pages/Guide/pages/DeferredMinter.tsx | 14 + .../App/pages/Guide/pages/Ekoke.tsx | 14 + .../components/App/pages/Guide/pages/Faq.tsx | 11 + .../App/pages/Guide/pages/Marketplace.tsx | 14 + .../App/pages/Guide/pages/Reward.tsx | 14 + .../App/pages/Guide/pages/RewardPool.tsx | 14 + .../App/pages/Guide/pages/Whitepaper.tsx | 14 + src/js/components/Footer.tsx | 2 +- src/js/utils/routes.ts | 1 + src/js/utils/seo.ts | 4 + src/styles.css | 5 + yarn.lock | 1959 +++++++++++++---- 21 files changed, 1936 insertions(+), 497 deletions(-) create mode 100644 src/js/components/App/pages/Guide/MdPage.tsx create mode 100644 src/js/components/App/pages/Guide/pages/Architecture.tsx create mode 100644 src/js/components/App/pages/Guide/pages/Deferred.tsx create mode 100644 src/js/components/App/pages/Guide/pages/DeferredData.tsx create mode 100644 src/js/components/App/pages/Guide/pages/DeferredMinter.tsx create mode 100644 src/js/components/App/pages/Guide/pages/Ekoke.tsx create mode 100644 src/js/components/App/pages/Guide/pages/Faq.tsx create mode 100644 src/js/components/App/pages/Guide/pages/Marketplace.tsx create mode 100644 src/js/components/App/pages/Guide/pages/Reward.tsx create mode 100644 src/js/components/App/pages/Guide/pages/RewardPool.tsx create mode 100644 src/js/components/App/pages/Guide/pages/Whitepaper.tsx diff --git a/package.json b/package.json index a6801f4..7f6a38d 100644 --- a/package.json +++ b/package.json @@ -33,32 +33,38 @@ "@react-google-maps/api": "^2.20.3", "chart.js": "^4.4.2", "metamask-react": "^2.7.0", - "react": "^18.2", + "property-information": "^6.5.0", + "react": "^19", "react-chartjs-2": "^5.2.0", - "react-dom": "^18.2", + "react-dom": "^19", "react-helmet": "^6.1.0", "react-icons": "^5.4.0", "react-loading-skeleton": "^3.5.0", + "react-markdown": "^9.0.1", "react-router-dom": "^6.26.1", + "remark-gfm": "^4.0.0", "viem": "^2.21.54", "web3": "^4.16.0" }, "devDependencies": { "@parcel/reporter-bundle-analyzer": "^2.11.0", - "@parcel/transformer-typescript-tsc": "^2.12.0", - "@types/react": "^18.2", - "@types/react-dom": "^18.2", + "@parcel/transformer-typescript-tsc": "^2.13.0", + "@types/react": "^19", + "@types/react-dom": "^19", "@types/react-helmet": "^6.1.11", "@typescript-eslint/eslint-plugin": "^8", "@typescript-eslint/parser": "^8", "buffer": "^5.5.0||^6.0.0", "eslint": "^8", "eslint-config-prettier": "^9.1", - "parcel": "^2.12", + "parcel": "^2.13", "postcss": "^8.4", "prettier": "^3", "process": "^0.11.10", "tailwindcss": "^3.4", "typescript": "^5.3" + }, + "@parcel/resolver-default": { + "packageExports": true } } diff --git a/sitemap.xml b/sitemap.xml index f141819..f413e7b 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -66,4 +66,9 @@ 2025-01-10 1.00 + + https://ekokedao.com/guide/reward + 2025-01-10 + 1.00 + diff --git a/src/js/components/App/Routes.tsx b/src/js/components/App/Routes.tsx index eb01586..f1cbd0d 100644 --- a/src/js/components/App/Routes.tsx +++ b/src/js/components/App/Routes.tsx @@ -3,6 +3,7 @@ import { Route as RouterRoute, Routes } from 'react-router-dom'; import { Route } from '../../utils/routes'; import SeoEngine from '../SeoEngine'; +import Container from '../reusable/Container'; // pages const Home = React.lazy(() => import('./pages/Home')); @@ -25,11 +26,33 @@ const ProfileContracts = React.lazy( // Guide const Guide = React.lazy(() => import('./pages/Guide')); +const GuideArchitecture = React.lazy( + () => import('./pages/Guide/pages/Architecture'), +); +const GuideDeferredData = React.lazy( + () => import('./pages/Guide/pages/DeferredData'), +); +const GuideDeferredMinter = React.lazy( + () => import('./pages/Guide/pages/DeferredMinter'), +); +const GuideDeferred = React.lazy(() => import('./pages/Guide/pages/Deferred')); +const GuideEkoke = React.lazy(() => import('./pages/Guide/pages/Ekoke')); +const GuideMarketplace = React.lazy( + () => import('./pages/Guide/pages/Marketplace'), +); +const GuideRewardPool = React.lazy( + () => import('./pages/Guide/pages/RewardPool'), +); +const GuideReward = React.lazy(() => import('./pages/Guide/pages/Reward')); +const GuideWhitepaper = React.lazy( + () => import('./pages/Guide/pages/Whitepaper'), +); +const GuideFaq = React.lazy(() => import('./pages/Guide/pages/Faq')); const AppRouter = () => ( <> -
+ } /> @@ -57,12 +80,52 @@ const AppRouter = () => ( {/* Guide */} } /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> {/* 404 */} } /> -
+ ); diff --git a/src/js/components/App/pages/About/Team.tsx b/src/js/components/App/pages/About/Team.tsx index d62aae1..17226ae 100644 --- a/src/js/components/App/pages/About/Team.tsx +++ b/src/js/components/App/pages/About/Team.tsx @@ -38,7 +38,7 @@ const Team = () => ( Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam diff --git a/src/js/components/App/pages/Guide/MdPage.tsx b/src/js/components/App/pages/Guide/MdPage.tsx new file mode 100644 index 0000000..ec084bd --- /dev/null +++ b/src/js/components/App/pages/Guide/MdPage.tsx @@ -0,0 +1,127 @@ +import * as React from 'react'; +import ReactMarkdown from 'react-markdown'; +import remarkGfm from 'remark-gfm'; +import 'property-information'; +import * as Icon from 'react-icons/fa6'; + +import { useAppContext } from '../../AppContext'; +import Container from '../../../reusable/Container'; +import Wrapper from './Wrapper'; +import Link from '../../../reusable/Link'; + +interface Props { + githubUrl: string; + url: string; +} + +const redirectRelativeImgToGithub = (url: string, src: string) => { + // get base of url + let base = url.split('/').slice(0, -1).join('/'); + + if (src.startsWith('./')) { + // replace ./ + return src.replace('./', `${base}/`); + } + + if (src.indexOf('../') === 0) { + // resolve `../` by removing last part of base + base = url; + while (src.indexOf('../') === 0) { + src = src.replace('../', ''); + base = base.split('/').slice(0, -1).join('/'); + } + + return `${base}/${src}`; + } + + return src; +}; + +const redirectHref = (href: string) => { + return href.replace('.md', '').toLowerCase(); +}; + +const MdPage = ({ url, githubUrl }: Props) => { + const { setAppError } = useAppContext(); + const [md, setMd] = React.useState(''); + + React.useEffect(() => { + fetch(url) + .then((res) => res.text()) + .then(setMd) + .catch((err) => { + console.error('Failed to load page', err); + setAppError('Failed to load page'); + }); + }, [url]); + + return ( + + + + + + View on GitHub + + + + + {md && ( + + {props.children as unknown as any} + + ); + }, + img: function ({ node, ...props }) { + if (!node) { + return null; + } + if (!node.properties.src) { + return null; + } + if (typeof node.properties.src !== 'string') { + return null; + } + const src = node.properties.src; + + props.src = redirectRelativeImgToGithub(url, src); + + return ( + {props.alt} + ); + }, + }} + remarkPlugins={[remarkGfm]} + > + {md} + + )} + + + + ); +}; + +export default MdPage; diff --git a/src/js/components/App/pages/Guide/Wrapper.tsx b/src/js/components/App/pages/Guide/Wrapper.tsx index dbbbf0e..32700c6 100644 --- a/src/js/components/App/pages/Guide/Wrapper.tsx +++ b/src/js/components/App/pages/Guide/Wrapper.tsx @@ -6,6 +6,7 @@ import * as FaIcon from 'react-icons/fa6'; import { Route } from '../../../../utils/routes'; import Container from '../../../reusable/Container'; import Link from '../../../reusable/Link'; +import Button from '../../../reusable/Button'; enum Item { Architecture = Route.GUIDE_ARCHITECTURE, @@ -16,6 +17,7 @@ enum Item { EkokeContracts = Route.GUIDE_CONTRACTS_EKOKE, MarketplaceContracts = Route.GUIDE_CONTRACTS_MARKETPLACE, RewardPoolContracts = Route.GUIDE_CONTRACTS_REWARD_POOL, + Reward = Route.GUIDE_REWARD, Whitepaper = Route.GUIDE_WHITEPAPER, } @@ -25,6 +27,16 @@ const menu = { url: Route.GUIDE_FAQ, icon: , }, + [Item.Whitepaper]: { + title: 'Whitepaper', + url: Route.GUIDE_WHITEPAPER, + icon: , + }, + [Item.Reward]: { + title: 'EKOKE Rewards', + url: Route.GUIDE_REWARD, + icon: , + }, [Item.Architecture]: { title: 'Architecture', url: Route.GUIDE_ARCHITECTURE, @@ -60,11 +72,6 @@ const menu = { url: Route.GUIDE_CONTRACTS_REWARD_POOL, icon: , }, - [Item.Whitepaper]: { - title: 'Whitepaper', - url: Route.GUIDE_WHITEPAPER, - icon: , - }, }; const routeToItems = { @@ -77,6 +84,7 @@ const routeToItems = { [Route.url(Route.GUIDE_CONTRACTS_MARKETPLACE)]: Item.MarketplaceContracts, [Route.url(Route.GUIDE_CONTRACTS_REWARD_POOL)]: Item.RewardPoolContracts, [Route.url(Route.GUIDE_WHITEPAPER)]: Item.Whitepaper, + [Route.url(Route.GUIDE_REWARD)]: Item.Reward, }; interface Props { @@ -85,36 +93,82 @@ interface Props { const Wrapper = ({ children }: Props) => ( - - - - - {children} + + + {children} ); -const Menu = () => { +const Menu = () => ( + <> + + + + + + + +); + +const MenuDesktop = () => ; + +const MenuMobile = () => { + const [isOpen, setIsOpen] = React.useState(false); + + if (!isOpen) { + return ( + + { + setIsOpen(true); + }} + > + + + + ); + } + + // is open + return ( + + + { + setIsOpen(false); + }} + size={32} + /> + + + + ); +}; + +const MenuInner = () => { const { pathname } = useLocation(); const current: Item = routeToItems[pathname]; return ( - - {Object.entries(menu).map(([key, value]) => ( - - + + {Object.entries(menu).map(([key, value]) => ( + + - - {value.icon} - {value.title} - - - - ))} - + href={value.url} + > + + {value.icon} + {value.title} + + + + ))} + + ); }; diff --git a/src/js/components/App/pages/Guide/pages/Architecture.tsx b/src/js/components/App/pages/Guide/pages/Architecture.tsx new file mode 100644 index 0000000..a950b3d --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/Architecture.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const Architecture = () => ( + +); + +export default Architecture; diff --git a/src/js/components/App/pages/Guide/pages/Deferred.tsx b/src/js/components/App/pages/Guide/pages/Deferred.tsx new file mode 100644 index 0000000..8a7eee8 --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/Deferred.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const Deferred = () => ( + +); + +export default Deferred; diff --git a/src/js/components/App/pages/Guide/pages/DeferredData.tsx b/src/js/components/App/pages/Guide/pages/DeferredData.tsx new file mode 100644 index 0000000..447b4b7 --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/DeferredData.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const DeferredData = () => ( + +); + +export default DeferredData; diff --git a/src/js/components/App/pages/Guide/pages/DeferredMinter.tsx b/src/js/components/App/pages/Guide/pages/DeferredMinter.tsx new file mode 100644 index 0000000..da183f9 --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/DeferredMinter.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const DeferredMinter = () => ( + +); + +export default DeferredMinter; diff --git a/src/js/components/App/pages/Guide/pages/Ekoke.tsx b/src/js/components/App/pages/Guide/pages/Ekoke.tsx new file mode 100644 index 0000000..6f191a1 --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/Ekoke.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const Ekoke = () => ( + +); + +export default Ekoke; diff --git a/src/js/components/App/pages/Guide/pages/Faq.tsx b/src/js/components/App/pages/Guide/pages/Faq.tsx new file mode 100644 index 0000000..d31e410 --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/Faq.tsx @@ -0,0 +1,11 @@ +import * as React from 'react'; +import Container from '../../../../reusable/Container'; +import Heading from '../../../../reusable/Heading'; + +const Faq = () => ( + + Frequently Asked Questions + +); + +export default Faq; diff --git a/src/js/components/App/pages/Guide/pages/Marketplace.tsx b/src/js/components/App/pages/Guide/pages/Marketplace.tsx new file mode 100644 index 0000000..0d9ce4f --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/Marketplace.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const Marketplace = () => ( + +); + +export default Marketplace; diff --git a/src/js/components/App/pages/Guide/pages/Reward.tsx b/src/js/components/App/pages/Guide/pages/Reward.tsx new file mode 100644 index 0000000..8388280 --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/Reward.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const Reward = () => ( + +); + +export default Reward; diff --git a/src/js/components/App/pages/Guide/pages/RewardPool.tsx b/src/js/components/App/pages/Guide/pages/RewardPool.tsx new file mode 100644 index 0000000..56d75dc --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/RewardPool.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const RewardPool = () => ( + +); + +export default RewardPool; diff --git a/src/js/components/App/pages/Guide/pages/Whitepaper.tsx b/src/js/components/App/pages/Guide/pages/Whitepaper.tsx new file mode 100644 index 0000000..f666e83 --- /dev/null +++ b/src/js/components/App/pages/Guide/pages/Whitepaper.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; + +import MdPage from '../MdPage'; + +const Whitepaper = () => ( + +); + +export default Whitepaper; diff --git a/src/js/components/Footer.tsx b/src/js/components/Footer.tsx index 2237017..c993618 100644 --- a/src/js/components/Footer.tsx +++ b/src/js/components/Footer.tsx @@ -13,7 +13,7 @@ import Paragraph from './reusable/Paragraph'; const Footer = () => { const year = new Date().getFullYear(); return ( -