Skip to content

Commit

Permalink
Updated favourites image
Browse files Browse the repository at this point in the history
* Added favourite option to song display page
* Safely handled direct navigation to songs outside of scope
* Allowed bottom nav to hide on scroll down
* Changed banner pattern
* Changed some grid containers to flex to allow them to display on old ios
  • Loading branch information
dons20 committed Mar 29, 2021
1 parent 3b19b69 commit e1da587
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 105 deletions.
6 changes: 6 additions & 0 deletions src/components/BottomNav/BottomNav.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@
position: fixed;
width: 100%;
z-index: 100;
transition: transform 0.25s ease-in-out;
will-change: transform;

&.--hidden {
transform: translateY(100%);
}

&.--disabled {
transform: scaleY(0);
z-index: -1;
}
Expand Down
82 changes: 25 additions & 57 deletions src/components/BottomNav/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,19 @@
import React, { useState, useEffect, useRef } from "react";
import { FaItunesNote, FaHome, FaStar } from "react-icons/fa";
import { useLocation, useHistory } from "react-router-dom";
import { useScrollPosition } from "components/CustomHooks";
import { useColorModeValue } from "@chakra-ui/color-mode";
import { useMediaQuery } from "@chakra-ui/media-query";
import { isMobile } from "react-device-detect";
import { Box, Text } from "@chakra-ui/layout";
import { Button } from "components";
import "./BottomNav.scss";

const scrollHeight = Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.body.clientHeight,
document.documentElement.clientHeight
),
offsetShow = scrollHeight;

function MobileNavBar() {
const { pathname } = useLocation();
const history = useHistory();
const [scrollingDown, setScrollingDown] = useState(false);
const prevPath = useRef<string | null>(null);
const [hidden] = useState(false);
const [transitioning] = useState(false);
const scrollPos = useRef(document.body.getBoundingClientRect().top);
const [iconsOnly] = useMediaQuery("(max-width: 475px)");
const footerBg = useColorModeValue("blue.600", "blue.600");
const footerColors = useColorModeValue("gray.100", "gray.100");
Expand All @@ -47,61 +36,40 @@ function MobileNavBar() {
},
];

/**
* Implements hide on scroll down, show on scroll up
* Will show if near the end of the page
*/
useScrollPosition(
({ prevPos, currPos }: PosT) => {
const shouldHide = currPos.y < prevPos.y;
const belowThreshold = currPos.y > offsetShow;
if (shouldHide !== hidden && !belowThreshold && !transitioning) {
//setHidden(shouldHide);
//triggerTransition();
} else if (belowThreshold && !transitioning) {
//setHidden(!shouldHide);
//triggerTransition();
}
},
[hidden],
null,
true,
120
);

useEffect(() => {
if (pathname !== prevPath.current) {
/* new Promise(resolve => {
resolve(
setTimeout(() => {
setTransitioning(false);
setHidden(false);
}, 300)
);
}); */
}
// Initial state
// var scrollPos = 0;
const scrollEventHandler = () => {
// detects new state and compares it with the new one
if (document.body.getBoundingClientRect().top > scrollPos.current) setScrollingDown(false);
else setScrollingDown(true);
// saves the new position for iteration.
scrollPos.current = document.body.getBoundingClientRect().top;
};

prevPath.current = pathname;
}, [pathname]);
// adding scroll event
window.addEventListener("scroll", scrollEventHandler);

/* function triggerTransition() {
setTransitioning(true);
new Promise(resolve => {
resolve(setTimeout(() => setTransitioning(false), 250));
});
} */
return () => {
window.removeEventListener("scroll", scrollEventHandler);
};
}, [setScrollingDown]);

/* function disableTransitionState() {
setTransitioning(false);
} */
useEffect(() => {
prevPath.current = pathname;
}, [pathname]);

function handleTabBarPress(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
const url = e.currentTarget.getAttribute("data-url") || "/";
history.push(url);
}

return (
<Box className={`bottom-nav${isMobile ? "" : " --hidden"}`} color={footerColors} bg={footerBg}>
<Box
className={`bottom-nav${isMobile ? "" : " --disabled"}${scrollingDown ? "" : " --hidden"}`}
color={footerColors}
bg={footerBg}
>
{tabValues.map(tab => (
<Button
data-url={tab.url}
Expand Down
2 changes: 1 addition & 1 deletion src/components/PictureHeader/PictureHeader.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
height: 100%;
display: block;
position: relative;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 28' width='56' height='28'%3E%3Cpath fill='%233182ce' fill-opacity='0.12' d='M56 26v2h-7.75c2.3-1.27 4.94-2 7.75-2zm-26 2a2 2 0 1 0-4 0h-4.09A25.98 25.98 0 0 0 0 16v-2c.67 0 1.34.02 2 .07V14a2 2 0 0 0-2-2v-2a4 4 0 0 1 3.98 3.6 28.09 28.09 0 0 1 2.8-3.86A8 8 0 0 0 0 6V4a9.99 9.99 0 0 1 8.17 4.23c.94-.95 1.96-1.83 3.03-2.63A13.98 13.98 0 0 0 0 0h7.75c2 1.1 3.73 2.63 5.1 4.45 1.12-.72 2.3-1.37 3.53-1.93A20.1 20.1 0 0 0 14.28 0h2.7c.45.56.88 1.14 1.29 1.74 1.3-.48 2.63-.87 4-1.15-.11-.2-.23-.4-.36-.59H26v.07a28.4 28.4 0 0 1 4 0V0h4.09l-.37.59c1.38.28 2.72.67 4.01 1.15.4-.6.84-1.18 1.3-1.74h2.69a20.1 20.1 0 0 0-2.1 2.52c1.23.56 2.41 1.2 3.54 1.93A16.08 16.08 0 0 1 48.25 0H56c-4.58 0-8.65 2.2-11.2 5.6 1.07.8 2.09 1.68 3.03 2.63A9.99 9.99 0 0 1 56 4v2a8 8 0 0 0-6.77 3.74c1.03 1.2 1.97 2.5 2.79 3.86A4 4 0 0 1 56 10v2a2 2 0 0 0-2 2.07 28.4 28.4 0 0 1 2-.07v2c-9.2 0-17.3 4.78-21.91 12H30zM7.75 28H0v-2c2.81 0 5.46.73 7.75 2zM56 20v2c-5.6 0-10.65 2.3-14.28 6h-2.7c4.04-4.89 10.15-8 16.98-8zm-39.03 8h-2.69C10.65 24.3 5.6 22 0 22v-2c6.83 0 12.94 3.11 16.97 8zm15.01-.4a28.09 28.09 0 0 1 2.8-3.86 8 8 0 0 0-13.55 0c1.03 1.2 1.97 2.5 2.79 3.86a4 4 0 0 1 7.96 0zm14.29-11.86c1.3-.48 2.63-.87 4-1.15a25.99 25.99 0 0 0-44.55 0c1.38.28 2.72.67 4.01 1.15a21.98 21.98 0 0 1 36.54 0zm-5.43 2.71c1.13-.72 2.3-1.37 3.54-1.93a19.98 19.98 0 0 0-32.76 0c1.23.56 2.41 1.2 3.54 1.93a15.98 15.98 0 0 1 25.68 0zm-4.67 3.78c.94-.95 1.96-1.83 3.03-2.63a13.98 13.98 0 0 0-22.4 0c1.07.8 2.09 1.68 3.03 2.63a9.99 9.99 0 0 1 16.34 0z'%3E%3C/path%3E%3C/svg%3E");
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='72' viewBox='0 0 36 72'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%233182ce' fill-opacity='0.23'%3E%3Cpath d='M2 6h12L8 18 2 6zm18 36h12l-6 12-6-12z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}

& .bgImg {
Expand Down
2 changes: 1 addition & 1 deletion src/components/PictureHeader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "./PictureHeader.scss";

function PictureHeader() {
const { meta } = useMainContext();
const headerOverlay = useColorModeValue("gray.800", "gray.800");
const headerOverlay = useColorModeValue("#0d222f", "#061a2b");

return (
<Box className="picture-header" bgColor={headerOverlay}>
Expand Down
9 changes: 7 additions & 2 deletions src/components/Songs/SongDisplay/SongDisplay.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@

& > .header {
align-items: center;
column-gap: 2rem;
gap: 15px;
display: grid;
font-weight: bold;
grid-template-columns: auto 1fr;
margin: auto;
max-width: 1000px;
width: 100%;
Expand All @@ -36,4 +35,10 @@
font-size: calc(10px + 1vmin);
font-weight: 600;
}

@media only screen and (min-width: 550px) {
& > .header {
grid-template-columns: auto 1fr 50px;
}
}
}
56 changes: 45 additions & 11 deletions src/components/Songs/SongDisplay/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { useEffect, Fragment, useMemo } from "react";
import { Box, Container, Text, IconButton } from "@chakra-ui/react";
import { useColorModeValue } from "@chakra-ui/color-mode";
import { useHistory, useParams } from "react-router-dom";
import { Box, Container, Text } from "@chakra-ui/layout";
import { Redirect, useHistory, useParams } from "react-router-dom";
import { updateFavesDB } from "helpers";
import { Helmet } from "react-helmet";
import { useMainContext } from "App";
import { Button } from "components";
import "./SongDisplay.scss";
import { FaHeart } from "react-icons/fa";

type ParamTypes = {
songID?: string;
Expand All @@ -14,12 +16,20 @@ type ParamTypes = {
function SongDisplay() {
const history = useHistory();
const { songID } = useParams<ParamTypes>();
const { songs, dispatch } = useMainContext();
const { songs, favourites, setFavourites, dispatch } = useMainContext();
const authorColor = useColorModeValue("#555555", "gray.300");
const songBG = useColorModeValue("gray.50", "inherit");
const songShadow = useColorModeValue("md", undefined);
const modalBG = useColorModeValue("gray.100", "gray.800");
const favActiveIconColor = useColorModeValue("var(--chakra-colors-red-500)", "var(--chakra-colors-red-300)");
const favIconColor = useColorModeValue("var(--chakra-colors-gray-600)", "var(--chakra-colors-gray-500)");
const favActiveIconBG = useColorModeValue("var(--chakra-colors-red-50)", "");
const songIndex = parseInt(songID || "1") - 1;
const songToRender = songs.find(song => song.number === songIndex + 1);
const songToRender = songs.find(song => song.number === songIndex + 1) || null;

useEffect(() => {
if (songs.length > 1) dispatch!({ type: "setTitle", payload: songToRender?.title || "" });
}, [dispatch, songs, songToRender]);

const songBody = useMemo(() => {
return (
Expand Down Expand Up @@ -50,11 +60,23 @@ function SongDisplay() {
);
}, [songs, songToRender]);

const backToIndex = () => history.push(`${process.env.PUBLIC_URL}/songs/index`);
if (songToRender === null) return <Redirect to="songs/index" />;

useEffect(() => {
if (songs.length > 1) dispatch!({ type: "setTitle", payload: songToRender!.title });
}, [dispatch, songs, songToRender]);
const isFavourite = favourites.includes(songToRender.number - 1);

const toggleFavourite = (number: number) => {
let faves = [];
if (favourites.includes(number - 1)) {
faves = favourites.filter(fave => fave !== number - 1);
setFavourites(faves);
} else {
faves = [...favourites, number - 1];
setFavourites(faves);
}
updateFavesDB(faves);
};

const backToIndex = () => history.push(`${process.env.PUBLIC_URL}/songs/index`);

return (
<Container className="container" bg={songBG} shadow={songShadow} my={4} py="1rem" px="1.5rem">
Expand All @@ -64,14 +86,26 @@ function SongDisplay() {
<Button onClick={backToIndex} pos="fixed" left={-5} top="14%" zIndex={100}>
Index
</Button>
<Box className="header">
<Box className="header" pos="relative" pr="5">
<Text># {songToRender!.number}</Text>
<Text>{songToRender!.title}</Text>
<IconButton
colorScheme={isFavourite ? "red" : "gray"}
bgColor={isFavourite ? favActiveIconBG : modalBG}
_hover={{ shadow: "md" }}
icon={<FaHeart color={isFavourite ? favActiveIconColor : favIconColor} />}
aria-label="Add to Favourites"
size="lg"
variant="outline"
className="faveIcon"
onClick={() => toggleFavourite(songToRender.number)}
maxW="60px"
/>
</Box>
<Box className="body">{songBody}</Box>
{songToRender!.author && (
{songToRender.author && (
<Text className="footer" color={authorColor}>
{songToRender!.author}
{songToRender.author}
</Text>
)}
</Container>
Expand Down
Loading

0 comments on commit e1da587

Please sign in to comment.