Skip to content

Commit

Permalink
Implementation of router & navigator
Browse files Browse the repository at this point in the history
  • Loading branch information
bclswl0827 committed Dec 13, 2023
1 parent 79add49 commit b982849
Show file tree
Hide file tree
Showing 16 changed files with 285 additions and 13 deletions.
26 changes: 23 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"scripts": {
"start": "BROWSER=none react-scripts start",
"build": "react-scripts build",
"build": "GENERATE_SOURCEMAP=false react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
Expand All @@ -35,6 +35,7 @@
]
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"tailwindcss": "^3.3.6"
}
}
5 changes: 1 addition & 4 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@
name="keywords"
content="AnyShake, Seismograph, Seismometer, Earthquake, Raspberry Pi, Linux, STM32, Arduino, ESP32, ESP8266"
/>
<title>
AnyShake - An Open-source & Low-cost Solution to 3-Component
Seismograph
</title>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>AnyShake | Listen to the Whispering Earth</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
29 changes: 24 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
import { Suspense } from "react";
import {
RouterProvider,
createBrowserRouter,
createHashRouter,
} from "react-router-dom";
import { routerConfig } from "./config/router";
import Loading from "./views/Loading";

const App = () => {
const { mode, router } = routerConfig;
const routers = router.map((item) => {
const { uri, index, component } = item;
return { path: uri, index, Component: component };
});

return (
<div className="w-full min-h-screen flex">
<h1 className="p-5 m-auto text-center font-bold text-2xl">
We're working on it!
</h1>
</div>
<Suspense fallback={<Loading />}>
<RouterProvider
router={
mode === "hash"
? createHashRouter(routers)
: createBrowserRouter(routers)
}
/>
</Suspense>
);
};

Expand Down
Binary file added src/assets/images/logo.webp
Binary file not shown.
16 changes: 16 additions & 0 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
interface FooterProps {
text: string;
copyright: string;
}

export const Footer = (props: FooterProps) => {
const { text, copyright } = props;
return (
<footer className="w-full bg-gray-200 text-gray-500 flex flex-col px-6 py-2 sm:flex-row justify-between">
<span className="text-xs text-center ml-8 md:ml-12">{text}</span>
<span className="text-sm text-center justify-center">
{copyright}
</span>
</footer>
);
};
7 changes: 7 additions & 0 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const Header = () => {
return (
<div className="justify-center w-full min-h-screen flex">
<span className="m-auto text-xl">We're working on it!</span>
</div>
);
};
95 changes: 95 additions & 0 deletions src/components/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { useState } from "react";
import { Link } from "react-router-dom";

const shouldHighlightLabel = (uri: string): boolean => {
const { pathname, hash } = window.location;
return (
hash.includes(uri) ||
(pathname.slice(pathname.length - 1) === uri.slice(uri.length - 1) &&
pathname.includes(uri))
);
};

interface NavigationProps {
title: string;
icon: string;
base: string;
menu: {
external?: boolean;
name: string;
uri: string;
}[];
}

const Navigation = (props: NavigationProps) => {
const { title, icon, menu, base } = props;
const [isMenuCollapsed, setIsMenuCollapsed] = useState(true);

return (
<nav className="bg-gray-100 shadow-xl">
<div className="flex flex-wrap items-center justify-between mx-auto p-3">
<Link
to={base}
className="flex items-center flex-shrink-0 mr-6"
>
<img className="w-16 h-16 mx-4" src={icon} alt="" />
<span className="font-semibold text-xl tracking-tight text-gray-700">
{title}
</span>
</Link>

<button
onClick={() => setIsMenuCollapsed(!isMenuCollapsed)}
className="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-sm md:hidden hover:bg-gray-200"
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="16"
width="14"
viewBox="0 0 448 512"
>
<path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z" />
</svg>
</button>

<div
className={`${
isMenuCollapsed && "hidden"
} w-full md:block md:w-auto`}
>
<ul className="font-medium flex flex-col px-8 py-4 mt-4 rounded-lg bg-gray-50 md:flex-row md:space-x-8 md:mt-0 md:bg-gray-100">
{menu.map(({ name, uri, external }, index) => (
<li key={`${index}-${uri}`}>
<Link
to={uri}
className={`${
shouldHighlightLabel(uri)
? `text-indigo-600`
: `text-gray-600`
} py-2 pl-3 pr-4 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-indigo-500 md:p-0 flex flex-row`}
target={external ? "_blank" : "_self"}
>
{name}
{external && (
<svg
xmlns="http://www.w3.org/2000/svg"
height="10"
width="10"
fill="currentColor"
viewBox="0 0 512 512"
className="m-1"
>
<path d="M352 0c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9L370.7 96 201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L416 141.3l41.4 41.4c9.2 9.2 22.9 11.9 34.9 6.9s19.8-16.6 19.8-29.6V32c0-17.7-14.3-32-32-32H352zM80 32C35.8 32 0 67.8 0 112V432c0 44.2 35.8 80 80 80H400c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32V432c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16H192c17.7 0 32-14.3 32-32s-14.3-32-32-32H80z" />
</svg>
)}
</Link>
</li>
))}
</ul>
</div>
</div>
</nav>
);
};

export default Navigation;
34 changes: 34 additions & 0 deletions src/config/menu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import icon from "../assets/images/logo.webp";

export const menuConfig = {
title: "AnyShake",
base: "/",
icon,
menu: [
{
external: false,
name: "Home",
uri: "/",
},
{
external: false,
name: "Documentation",
uri: "/documentation",
},
{
external: false,
name: "Features",
uri: "/features",
},
{
external: false,
name: "Contribution",
uri: "/contribution",
},
{
external: true,
name: "GitHub",
uri: "https://github.com/anyshake",
},
],
};
35 changes: 35 additions & 0 deletions src/config/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { lazy } from "react";
import Error from "../views/Error";

const Home = lazy(() => import("../views/Home"));

export const routerConfig = {
mode: "hash",
router: [
{
index: true,
component: Home,
uri: "/",
},
{
index: true,
component: Home,
uri: "/documentation",
},
{
index: true,
component: Home,
uri: "/features",
},
{
index: true,
component: Home,
uri: "/contribution",
},
{
index: false,
component: Error,
uri: "*",
}, // 404 Error Page
],
};
5 changes: 5 additions & 0 deletions src/config/site.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const siteConfig = {
title: "AnyShake",
slogan: "Listen to the Whispering Earth",
copyright: ${new Date().getFullYear()} AnyShake`,
};
5 changes: 5 additions & 0 deletions src/custom.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare module "*.jpg";
declare module "*.png";
declare module "*.jpeg";
declare module "*.gif";
declare module "*.webp";
6 changes: 6 additions & 0 deletions src/helpers/setTitle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { siteConfig } from "../config/site";

export const setTitle = (paging: string): void => {
const { title } = siteConfig;
document.title = `${paging} - ${title}`;
};
5 changes: 5 additions & 0 deletions src/views/Error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Error = () => {
return <div>Error</div>;
};

export default Error;
22 changes: 22 additions & 0 deletions src/views/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useEffect } from "react";
import { Footer } from "../components/Footer";
import Navigation from "../components/Navigation";
import { Header } from "../components/Header";
import { menuConfig } from "../config/menu";
import { siteConfig } from "../config/site";
import { setTitle } from "../helpers/setTitle";

const Home = () => {
const { slogan, copyright } = siteConfig;
useEffect(() => setTitle("Home"), []);

return (
<div>
<Navigation {...menuConfig} />
<Header />
<Footer text={slogan} copyright={copyright} />
</div>
);
};

export default Home;
5 changes: 5 additions & 0 deletions src/views/Loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Loading = () => {
return <div>Loading</div>;
};

export default Loading;

0 comments on commit b982849

Please sign in to comment.