|
1 | 1 | import React, { useState, useEffect, useRef, useMemo } from "react";
|
2 |
| -// import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; |
3 |
| - |
4 |
| -import Nav from "./components/Nav"; |
5 |
| -import Search from "./components/Search"; |
6 |
| -import Slider, { CardSlider } from "./components/Slider"; |
7 |
| -import Social from "./components/Social"; |
8 |
| -import logo from "./logos/logo_trans.svg"; |
9 |
| -import imgLogo from "./logos/logo_colored.svg"; |
10 |
| -import Grid from "./components/Grid"; |
11 |
| -import DropdownMenu from "./components/DropdownMenu"; |
12 |
| - |
13 |
| -// import data.json |
14 |
| -import data from "./data.json"; |
15 |
| - |
16 |
| -// custom hooks |
17 |
| -import { useWindowSize } from "./custom_hooks/useWindowSize"; |
18 |
| -import { useSize } from "./custom_hooks/useSize"; |
19 |
| -import useIntersectionObserver from "@react-hook/intersection-observer"; |
| 2 | +import { Switch, Route } from "react-router-dom"; |
| 3 | +import Header from "./components/Header"; |
20 | 4 | import Footer from "./components/Footer";
|
| 5 | +import Contact from "./components/Contact"; |
| 6 | +import Content from "./components/Content"; |
| 7 | +import ProductDetail from "./components/ProductDetail"; |
| 8 | +import { useOnscreen } from "./custom_hooks/useOnscreen"; |
| 9 | +import { useFetch } from "./custom_hooks/useFetch"; |
21 | 10 |
|
22 |
| -function App() { |
23 |
| - const [min, setMin] = useState(false); |
24 |
| - const aboutRef = useRef(null); |
25 |
| - const contactRef = useRef(null); |
26 |
| - const headerRef = useRef(null); |
| 11 | +function App({ hideLoader }) { |
| 12 | + // States & Refs |
| 13 | + const [ref, setRef] = useState(null); |
| 14 | + const [visible, setvisible] = useState(false); |
| 15 | + const [height, setHeight] = useState(0); |
27 | 16 | const showCaseRef = useRef(null);
|
28 |
| - const options = { |
29 |
| - root: null, |
30 |
| - rootMargin: "0px", |
31 |
| - threshold: 1, |
32 |
| - }; |
33 | 17 |
|
34 | 18 | // Custom hooks
|
35 |
| - const { isIntersecting: homeIntersect, intersectionRatio: homeRatio } = |
36 |
| - useIntersectionObserver(showCaseRef, options); |
37 |
| - const { isIntersecting: aboutIntersect } = useIntersectionObserver( |
38 |
| - aboutRef, |
39 |
| - options |
40 |
| - ); |
41 |
| - const { isIntersecting: contactIntersect } = useIntersectionObserver( |
42 |
| - contactRef, |
43 |
| - options |
44 |
| - ); |
45 |
| - |
46 |
| - const { width } = useWindowSize(); |
47 |
| - const size = useSize(headerRef); |
| 19 | + const { ratio: homeRatio } = useOnscreen(showCaseRef, { threshold: 1 }); |
| 20 | + const bikes = useFetch("http://localhost:8000/products/bicycles"); |
| 21 | + const heaters = useFetch("http://localhost:8000/products/heaters"); |
48 | 22 |
|
49 |
| - const { bottom } = useMemo(() => ({ bottom: size?.bottom }), [size?.bottom]); |
| 23 | + // Memorize hook |
50 | 24 | const ratio = useMemo(() => homeRatio, [homeRatio]);
|
51 | 25 |
|
| 26 | + // side effects to hide preloader when the App component mounts. |
| 27 | + useEffect(hideLoader, [hideLoader]); |
| 28 | + |
| 29 | + // side effects to check the div.showCase ratio intersect with vp |
52 | 30 | useEffect(() => {
|
53 |
| - ratio < 1 ? setMin(true) : setMin(false); |
| 31 | + ratio < 1 ? setvisible(true) : setvisible(false); |
54 | 32 | }, [ratio]);
|
55 | 33 |
|
56 |
| - return ( |
57 |
| - <div className="App"> |
58 |
| - <header ref={headerRef} className="header"> |
59 |
| - <div className={`header__container ${min ? "reset-dimensions" : ""}`}> |
60 |
| - <div className="header__left"> |
61 |
| - <a href="#home" className="header__logo"> |
62 |
| - <img src={logo} alt="company logo" /> |
63 |
| - </a> |
64 |
| - </div> |
65 |
| - <div className="header__right"> |
66 |
| - <Nav |
67 |
| - intersectings={[homeIntersect, aboutIntersect, contactIntersect]} |
68 |
| - /> |
69 |
| - <Search /> |
70 |
| - </div> |
71 |
| - </div> |
72 |
| - <div className="header__cat"> |
73 |
| - <DropdownMenu min={min} /> |
74 |
| - </div> |
75 |
| - </header> |
76 |
| - <main> |
77 |
| - <div |
78 |
| - ref={showCaseRef} |
79 |
| - id="home" |
80 |
| - className="showCase" |
81 |
| - style={{ marginBlockStart: `${bottom + 20}px` }} |
82 |
| - > |
83 |
| - <Slider sliders={data.sliders} /> |
84 |
| - </div> |
85 |
| - {/* .showCase end */} |
86 |
| - <section id="bicycles" className="cardWrapper"> |
87 |
| - <div className="wrapper"> |
88 |
| - <h2>Bicycles</h2> |
89 |
| - {!(width >= 500) ? ( |
90 |
| - <CardSlider cards={data.bicycles} /> |
91 |
| - ) : ( |
92 |
| - <Grid cards={data.bicycles} /> |
93 |
| - )} |
94 |
| - </div> |
95 |
| - </section> |
96 |
| - {/* .bicycles end */} |
| 34 | + // handle the change in header's height. |
| 35 | + function updateHeight(recBottom) { |
| 36 | + setHeight(recBottom); |
| 37 | + } |
97 | 38 |
|
98 |
| - <section id="heaters" className="cardWrapper"> |
99 |
| - <div className="wrapper"> |
100 |
| - <h2>Heaters</h2> |
101 |
| - {!(width >= 500) ? ( |
102 |
| - <CardSlider cards={data.heaters} /> |
103 |
| - ) : ( |
104 |
| - <Grid cards={data.heaters} /> |
105 |
| - )} |
106 |
| - </div> |
107 |
| - </section> |
108 |
| - {/* .heaters end */} |
109 | 39 |
|
110 |
| - <section ref={aboutRef} id="about" className="about"> |
111 |
| - <div className="about__wrapper"> |
112 |
| - <img className="about__img" src={imgLogo} alt="company img" /> |
113 |
| - <div className="about__info"> |
114 |
| - <p> |
115 |
| - Lorem ipsum is placeholder text commonly used in the graphic, |
116 |
| - print , and publishing industries for previewing layouts and |
117 |
| - Lorem ipsum is placeholder text commonly used in the graphic, |
118 |
| - print , and publishing industries for previewing layouts and |
119 |
| - visual mockups. visual mockups.{" "} |
120 |
| - </p> |
121 |
| - </div> |
122 |
| - </div> |
123 |
| - </section> |
124 |
| - {/* .about end */} |
| 40 | + // callback prop to pass the aboutRef to the Header and then down to Nav |
| 41 | + const passRef = (aboutRef) => setRef(aboutRef); |
125 | 42 |
|
126 |
| - <section ref={contactRef} id="contact" className="contact"> |
127 |
| - <div className="contact__wrapper"> |
128 |
| - <h2>Contact me</h2> |
129 |
| - <p> |
130 |
| - Feel free to contact me directly by sending a message in what's |
131 |
| - app or via facebook. choose what you're comfortable with. |
132 |
| - </p> |
133 |
| - <div className="socials"> |
134 |
| - <Social /> |
135 |
| - </div> |
136 |
| - </div> |
137 |
| - </section> |
138 |
| - {/* .contact end */} |
139 |
| - </main> |
140 |
| - <Footer /> |
| 43 | + const style = { |
| 44 | + color: "hsl(120, 2%, 70%)", |
| 45 | + bg: "hsl(0, 62%, 36%)", |
| 46 | + }; |
| 47 | + |
| 48 | + return ( |
| 49 | + <div className="App"> |
| 50 | + <Switch> |
| 51 | + <Route exact path="/"> |
| 52 | + <Header visible={visible} updateHeight={updateHeight} refs={ref} /> |
| 53 | + <Content |
| 54 | + showCaseRef={showCaseRef} |
| 55 | + height={height} |
| 56 | + bikes={bikes} |
| 57 | + heaters={heaters} |
| 58 | + passRef={passRef} |
| 59 | + /> |
| 60 | + <Footer theme={style} /> |
| 61 | + </Route> |
| 62 | + <Route path="/contact"> |
| 63 | + <Contact /> |
| 64 | + </Route> |
| 65 | + <Route path="/products/:id"> |
| 66 | + <ProductDetail /> |
| 67 | + </Route> |
| 68 | + </Switch> |
141 | 69 | </div>
|
142 | 70 | );
|
143 | 71 | }
|
|
0 commit comments