aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Zelent <marcin@zelent.net>2021-01-08 19:47:37 +0100
committerMarcin Zelent <marcin@zelent.net>2021-01-08 19:47:37 +0100
commit628632ff5092f1e3cf6c968d9bdfbd9a24f59541 (patch)
treefeddb4e82267bba700a15a6a7091f922f48cae40 /components/Sidebar
Initial commit
Diffstat (limited to 'components/Sidebar')
-rw-r--r--components/Sidebar/Sidebar.module.css54
-rw-r--r--components/Sidebar/Sidebar.tsx71
2 files changed, 125 insertions, 0 deletions
diff --git a/components/Sidebar/Sidebar.module.css b/components/Sidebar/Sidebar.module.css
new file mode 100644
index 0000000..a3c8a1a
--- /dev/null
+++ b/components/Sidebar/Sidebar.module.css
@@ -0,0 +1,54 @@
+.aside {
+ min-width: 272px;
+ height: 100%;
+ padding: 5px;
+ display: flex;
+ flex-direction: column;
+ border-right: 1px solid #e5e5e5;
+ box-shadow: -2px 0 10px #000;
+ z-index: 9999;
+ background-color: #fff;
+}
+
+.aside h2 {
+ padding-left: 1.5rem;
+}
+
+.list {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ overflow-y: auto;
+}
+
+.listItem {
+ margin-bottom: 5px;
+ padding: 1rem 2rem 1rem 1.5rem;
+ display: block;
+ border-radius: 10px;
+ cursor: pointer;
+ user-select: none;
+ outline: currentcolor none medium;
+}
+
+.listItem:hover {
+ background-color: #f5f5f5;
+}
+
+.listItemActive {
+ background-color: #e9f3ff !important;
+}
+
+@media only screen and (max-width: 500px) {
+ .aside {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: -100vw;
+ transition: left 0.3s ease-in;
+ }
+
+ .asideOpen {
+ left: 0;
+ }
+}
diff --git a/components/Sidebar/Sidebar.tsx b/components/Sidebar/Sidebar.tsx
new file mode 100644
index 0000000..6b0473a
--- /dev/null
+++ b/components/Sidebar/Sidebar.tsx
@@ -0,0 +1,71 @@
+import { useEffect, useRef } from 'react';
+
+import { Trip } from 'models';
+import { secondsToTimeString } from 'lib/util';
+
+import styles from './Sidebar.module.css';
+
+interface Props {
+ trips: Trip[];
+ currentTrip: Trip;
+ asideOpen: boolean;
+ handleClose: () => void;
+ setCurrentTrip: (trip: Trip) => void;
+}
+
+export default function Sidebar({
+ trips,
+ currentTrip,
+ asideOpen,
+ handleClose,
+ setCurrentTrip,
+}: Props): JSX.Element {
+ const wrapperRef = useRef(null);
+
+ useEffect(() => {
+ function handleClickOutside(e: MouseEvent) {
+ if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
+ handleClose();
+ }
+ }
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => {
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, [wrapperRef]);
+
+ function handleTripChange(trip: Trip): void {
+ setCurrentTrip(trip);
+ handleClose();
+ }
+
+ return (
+ <aside ref={wrapperRef} className={`${styles.aside} ${asideOpen && styles.asideOpen}`}>
+ <h2>Trips</h2>
+ <ul className={styles.list}>
+ {trips.map((t) => (
+ <li key={t.name}>
+ <a
+ onClick={() => handleTripChange(t)}
+ onKeyPress={() => handleTripChange(t)}
+ tabIndex={0}
+ role="menuitem"
+ className={`${styles.listItem} ${
+ t.name === currentTrip.name && styles.listItemActive
+ }`}
+ >
+ <b>{new Date(t.start).toDateString()}</b>
+ <br />
+ Total distance: {t.distance} km
+ <br />
+ Duration: {secondsToTimeString(t.duration)}
+ <br />
+ Average speed: {t.speed} km/h
+ </a>
+ </li>
+ ))}
+ </ul>
+ </aside>
+ );
+}