Skip to content

Commit 58b93f6

Browse files
committed
production-v1
1 parent 99745f4 commit 58b93f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2028
-810
lines changed

package-lock.json

+306-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
"@testing-library/jest-dom": "^5.14.1",
99
"@testing-library/react": "^11.2.7",
1010
"@testing-library/user-event": "^12.8.3",
11+
"axios": "^0.21.4",
1112
"node-sass": "^6.0.1",
1213
"react": "^17.0.2",
1314
"react-dom": "^17.0.2",
1415
"react-hook-form": "^7.13.0",
1516
"react-icons": "^4.2.0",
1617
"react-router-dom": "^5.2.1",
1718
"react-scripts": "4.0.3",
19+
"react-spinners": "^0.11.0",
20+
"react-transition-group": "^4.4.2",
1821
"swiper": "^6.8.1",
1922
"web-vitals": "^1.1.2"
2023
},

public/imgs/showCase/Bikes.png

809 KB
Loading

public/imgs/showCase/Third-slide.png

703 KB
Loading

public/imgs/showCase/heatrers.png

284 KB
Loading

public/index.html

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
<body>
1313
<div id="modal"></div>
1414
<div id="root"></div>
15+
<div class="loader">
16+
<div></div>
17+
<div></div>
18+
</div>
1519

1620
</body>
1721

src/App.js

+53-125
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,71 @@
11
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";
204
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";
2110

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);
2716
const showCaseRef = useRef(null);
28-
const options = {
29-
root: null,
30-
rootMargin: "0px",
31-
threshold: 1,
32-
};
3317

3418
// 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");
4822

49-
const { bottom } = useMemo(() => ({ bottom: size?.bottom }), [size?.bottom]);
23+
// Memorize hook
5024
const ratio = useMemo(() => homeRatio, [homeRatio]);
5125

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
5230
useEffect(() => {
53-
ratio < 1 ? setMin(true) : setMin(false);
31+
ratio < 1 ? setvisible(true) : setvisible(false);
5432
}, [ratio]);
5533

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+
}
9738

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 */}
10939

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);
12542

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>
14169
</div>
14270
);
14371
}

src/assets/logo_colored.svg

+1
Loading

src/components/About.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { useOnscreen } from "../custom_hooks/useOnscreen";
2+
import { useEffect, useRef } from "react";
3+
4+
function About() {
5+
const infoRef = useRef(null);
6+
7+
const { isIntersecting } = useOnscreen(infoRef);
8+
9+
// side effect to check if element intersecting with vp & then adding the corresponding animation.
10+
useEffect(() => {}, []);
11+
12+
return (
13+
<>
14+
<div className="about__wrapper container">
15+
<div
16+
ref={infoRef}
17+
className={` about__info ${isIntersecting && "slide-left"}`}
18+
>
19+
<h2>About us</h2>
20+
<p>
21+
<b>Momo Alrayah</b> is a company based in Japan stablished a few years ago, our job is
22+
to provide you reliable and affordable products with almost no
23+
shipping cost from Asia all the way to Africa.
24+
<blockquote>
25+
<i>
26+
Choose what's in your best interest and leave us all the heavy
27+
lifting.
28+
</i>
29+
</blockquote>
30+
</p>
31+
</div>
32+
</div>
33+
</>
34+
);
35+
}
36+
37+
export default About;

src/components/CardDetails.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
function CardDetails({ header, children, price, openForm }) {
2+
// console.log('title:', header)
23
return (
34
<div className="card">
45
<div className="card__content">{children}</div>
56
<div className="card__footer">
67
<span>
78
Price: <span className="price">{price}</span>
89
</span>
9-
<button onClick={(e) => openForm(e, { title: header })}>Request</button>
10+
<button onClick={(e) => openForm(e, { name: header })}>Request</button>
1011
</div>
1112
</div>
1213
);

src/components/CardGrid.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Link } from "react-router-dom";
2+
import { useRef } from "react";
3+
import { useOnscreen } from "../custom_hooks/useOnscreen";
4+
5+
function CardGrid({ product }) {
6+
const ref = useRef(null);
7+
8+
const { isIntersecting } = useOnscreen(ref);
9+
10+
return (
11+
<>
12+
<div
13+
ref={ref}
14+
key={product.id}
15+
style={{ transitionDelay: 0.035 * product.id + "s" }}
16+
className={`products__card ${isIntersecting && "fade-in"}`}
17+
>
18+
<div className="products__img ">
19+
<img src={product.image_path} alt="product img" />
20+
</div>
21+
<div className="products__content">
22+
<h4>{product.name}</h4>
23+
<p>{product.description.substring(0, 99).trim() + "..."}</p>
24+
</div>
25+
<div className="products__footer">
26+
<Link to={`/products/${product.id}`}>see more</Link>
27+
</div>
28+
</div>
29+
</>
30+
);
31+
}
32+
33+
export default CardGrid;

src/components/Contact.js

+33-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,38 @@
1-
1+
import Form from "./Form";
2+
import { Link } from "react-router-dom";
3+
import logo from "../logos/logo_trans.svg";
24

35
function Contact() {
4-
return(
5-
<div>
6-
<h2>Contact page</h2>
6+
return (
7+
<div className="contact">
8+
<header className="top">
9+
<div className="top__logo">
10+
<Link to="/">
11+
<img src={logo} alt="company logo" />
12+
</Link>
13+
</div>
14+
<Link to="/">home</Link>
15+
16+
<div className="custom-shape-divider-bottom-1632582134 top__waves">
17+
<svg
18+
data-name="Layer 1"
19+
xmlns="http://www.w3.org/2000/svg"
20+
viewBox="0 0 1200 120"
21+
preserveAspectRatio="none"
22+
>
23+
<path
24+
d="M985.66,92.83C906.67,72,823.78,31,743.84,14.19c-82.26-17.34-168.06-16.33-250.45.39-57.84,11.73-114,31.07-172,41.86A600.21,600.21,0,0,1,0,27.35V120H1200V95.8C1132.19,118.92,1055.71,111.31,985.66,92.83Z"
25+
className="shape-fill"
26+
></path>
27+
</svg>
728
</div>
8-
)
29+
</header>
30+
<main className="contact__content">
31+
<h2>reach me</h2>
32+
<Form social={true} />
33+
</main>
34+
</div>
35+
);
936
}
1037

11-
export default Contact;
38+
export default Contact;

0 commit comments

Comments
 (0)