Skip to content

Commit 1f38c2a

Browse files
authored
Merge pull request #9 from atlp-rwanda/ft-create-landing-page-187862829
[#187862829] ft-create-landing-page
2 parents 04b498f + 3ecd87a commit 1f38c2a

27 files changed

+741
-59
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/coverage
88

99
# production
10-
/build
10+
/dist
1111

1212
# misc
1313
.DS_Store

package-lock.json

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

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"react-icons": "^5.2.1",
2020
"react-redux": "^9.1.2",
2121
"react-router-dom": "^6.24.0",
22+
"react-spinners": "^0.14.1",
2223
"sass": "^1.77.6",
2324
"save-dev": "0.0.1-security"
2425
},

public/assets/left-bottom.png

26.7 KB
Loading

public/assets/left-top.png

24.1 KB
Loading

public/assets/middle.png

95.2 KB
Loading

public/assets/right-bottom.png

21.2 KB
Loading

public/assets/right-top.png

22 KB
Loading

public/assets/shoe1.jpeg

6.91 KB
Loading

public/assets/shoe2.jpeg

8.79 KB
Loading

public/assets/shoe3.jpeg

5.76 KB
Loading

public/assets/shoe4.jpeg

6.57 KB
Loading

src/components/layout/Footer.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,4 @@ function Footer() {
182182
</footer>
183183
);
184184
}
185-
export default Footer;
185+
export default Footer;

src/components/layout/Header.tsx

+33-20
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { IoCartOutline } from "react-icons/io5";
99
import { IoLogOutSharp } from "react-icons/io5";
1010
import { FaUserClock } from "react-icons/fa6";
1111
import { FaChevronDown } from "react-icons/fa";
12+
import { NavLink } from "react-router-dom";
1213

1314
import "../../styles/Header.scss";
1415

@@ -109,28 +110,28 @@ function Header() {
109110
<div className="order__dropdown">
110111
<ul className="order__list">
111112
<li>
112-
<a href="#" className="order__link">
113+
<NavLink to="/my-orders" className="order__link">
113114
<FaBuildingCircleCheck className="order__icon" />
114115
<span className="order__text">My Orders</span>
115-
</a>
116+
</NavLink>
116117
</li>
117118
<li>
118-
<a href="#" className="order__link">
119+
<NavLink to="/wishlist" className="order__link">
119120
<FaBuildingCircleCheck className="order__icon" />
120121
<span className="order__text">WishList</span>
121-
</a>
122+
</NavLink>
122123
</li>
123124
<li>
124-
<a href="#" className="order__link">
125+
<NavLink to="/profile-settings" className="order__link">
125126
<FaUserClock className="order__icon" />
126127
<span className="order__text">Profile Settings</span>
127-
</a>
128+
</NavLink>
128129
</li>
129130
<li>
130-
<a href="#" className="order__link">
131+
<NavLink to="/login" className="order__link">
131132
<IoLogOutSharp className="order__icon" />
132133
<span className="order__text">Login</span>
133-
</a>
134+
</NavLink>
134135
</li>
135136
</ul>
136137
</div>
@@ -141,23 +142,35 @@ function Header() {
141142
<div className="header__nav">
142143
<nav>
143144
<ul>
144-
<li>
145-
<a href="#">Home</a>
145+
<li className="nav__item">
146+
<NavLink to="/" className={({ isActive }) => (isActive ? 'active' : '')}>
147+
Home
148+
</NavLink>
146149
</li>
147-
<li>
148-
<a href="#">Shops</a>
150+
<li className="nav__item">
151+
<NavLink to="/shops" className={({ isActive }) => (isActive ? 'active' : '')}>
152+
Shops
153+
</NavLink>
149154
</li>
150-
<li>
151-
<a href="#">Products</a>
155+
<li className="nav__item">
156+
<NavLink to="/products" className={({ isActive }) => (isActive ? 'active' : '')}>
157+
Products
158+
</NavLink>
152159
</li>
153-
<li>
154-
<a href="#">Services</a>
160+
<li className="nav__item">
161+
<NavLink to="/services" className={({ isActive }) => (isActive ? 'active' : '')}>
162+
Services
163+
</NavLink>
155164
</li>
156-
<li>
157-
<a href="#">Contact-Us</a>
165+
<li className="nav__item">
166+
<NavLink to="/contact-us" className={({ isActive }) => (isActive ? 'active' : '')}>
167+
Contact-Us
168+
</NavLink>
158169
</li>
159-
<li>
160-
<a href="#">About-us</a>
170+
<li className="nav__item">
171+
<NavLink to="/about-us" className={({ isActive }) => (isActive ? 'active' : '')}>
172+
About-us
173+
</NavLink>
161174
</li>
162175
</ul>
163176
</nav>

src/components/layout/Sample.tsx

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/* eslint-disable */
2+
import React, { useState, useEffect, useRef } from 'react';
3+
import { TfiHeadphoneAlt } from "react-icons/tfi";
4+
import { VscWorkspaceTrusted } from "react-icons/vsc";
5+
import { LiaShippingFastSolid } from "react-icons/lia";
6+
import { FaHandHoldingUsd } from "react-icons/fa";
7+
import { GoDotFill } from "react-icons/go";
8+
import { FaChevronCircleLeft, FaChevronCircleRight } from "react-icons/fa";
9+
import '../../styles/index.scss';
10+
11+
const images = [
12+
'/assets/middle.png',
13+
'/assets/shoe2.jpeg',
14+
'/assets/shoe3.jpeg'
15+
];
16+
17+
const Sample: React.FC = () => {
18+
const [currentIndex, setCurrentIndex] = useState(0);
19+
const intervalRef = useRef<NodeJS.Timeout | null>(null);
20+
21+
const handleLeftClick = () => {
22+
setCurrentIndex((prevIndex) => (prevIndex === 0 ? images.length - 1 : prevIndex - 1));
23+
};
24+
25+
const handleRightClick = () => {
26+
setCurrentIndex((prevIndex) => (prevIndex === images.length - 1 ? 0 : prevIndex + 1));
27+
};
28+
29+
const startImageChangeInterval = () => {
30+
intervalRef.current = setInterval(() => {
31+
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length);
32+
}, 5000);
33+
};
34+
35+
useEffect(() => {
36+
startImageChangeInterval();
37+
return () => {
38+
if (intervalRef.current) {
39+
clearInterval(intervalRef.current);
40+
}
41+
};
42+
}, []);
43+
44+
useEffect(() => {
45+
if (intervalRef.current) {
46+
clearInterval(intervalRef.current);
47+
startImageChangeInterval();
48+
}
49+
}, [currentIndex]);
50+
51+
return (
52+
<div>
53+
<div className="sampleImages1">
54+
<div className="sample1">
55+
<div className="menShoe">
56+
<div className="text-container">
57+
<p>Men's Shoes</p>
58+
<button>View &gt;</button>
59+
</div>
60+
</div>
61+
<div className="phones">
62+
<div className="text-container">
63+
<p>Phones</p>
64+
<button>View &gt;</button>
65+
</div>
66+
</div>
67+
</div>
68+
<div className="sample2" style={{ backgroundImage: `url(${images[currentIndex]})` }}>
69+
<div className="arrow left" onClick={handleLeftClick}>
70+
<FaChevronCircleLeft className="icon-arrow" />
71+
</div>
72+
<div className="arrow right" onClick={handleRightClick}>
73+
<FaChevronCircleRight className="icon-arrow" />
74+
</div>
75+
<div className="dots">
76+
{images.map((_, index) => (
77+
<GoDotFill
78+
key={index}
79+
className="icon-dots"
80+
style={{ color: currentIndex === index ? '#ff6d18' : '#fff' }}
81+
/>
82+
))}
83+
</div>
84+
</div>
85+
<div className="sample3">
86+
<div className="womenShoe">
87+
<div className="text-container">
88+
<p>Women's Shoes</p>
89+
<button>View &gt;</button>
90+
</div>
91+
</div>
92+
<div className="accessories">
93+
<div className="text-container">
94+
<p>Accessories</p>
95+
<button>View &gt;</button>
96+
</div>
97+
</div>
98+
</div>
99+
</div>
100+
<div className="trust-container">
101+
<div className="trust">
102+
<TfiHeadphoneAlt className="icon" />
103+
<div className="name">
104+
<h2>Responsive</h2>
105+
<p>Customer service available 24/7</p>
106+
</div>
107+
</div>
108+
<div className="trust">
109+
<VscWorkspaceTrusted className="icon" />
110+
<div className="name">
111+
<h2>Secure</h2>
112+
<p>Certified marketplace since 2024</p>
113+
</div>
114+
</div>
115+
<div className="trust">
116+
<LiaShippingFastSolid className="icon" />
117+
<div className="name">
118+
<h2>Shipping</h2>
119+
<p>Free, fast, and reliable worldwide</p>
120+
</div>
121+
</div>
122+
<div className="trust">
123+
<FaHandHoldingUsd className="icon" />
124+
<div className="name">
125+
<h2>Transparent</h2>
126+
<p>Free return policy</p>
127+
</div>
128+
</div>
129+
</div>
130+
</div>
131+
);
132+
};
133+
134+
export default Sample;

src/components/product/Product.tsx

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* eslint-disable */
2+
import React, { useState, useRef } from 'react';
3+
import { CiHeart } from "react-icons/ci";
4+
import { PiShoppingCartThin } from "react-icons/pi";
5+
import '../../styles/index.scss';
6+
7+
interface ProductProps {
8+
images: string[];
9+
name: string;
10+
price: string;
11+
stock: number;
12+
description: string;
13+
discount: number;
14+
}
15+
16+
const Product: React.FC<ProductProps> = ({ images, name, price, stock, description, discount }) => {
17+
const [currentImageIndex, setCurrentImageIndex] = useState(0);
18+
const intervalRef = useRef<NodeJS.Timeout | null>(null);
19+
20+
const handleMouseEnter = () => {
21+
intervalRef.current = setInterval(() => {
22+
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % images.length);
23+
}, 2000);
24+
};
25+
26+
const handleMouseLeave = () => {
27+
if (intervalRef.current) {
28+
clearInterval(intervalRef.current);
29+
}
30+
setCurrentImageIndex(0);
31+
};
32+
33+
const truncateDescription = (desc: string, length: number) => {
34+
return desc.length > length ? `${desc.substring(0, length)}...` : desc;
35+
};
36+
37+
return (
38+
<div className="product">
39+
<div
40+
className="product-image-container"
41+
onMouseEnter={handleMouseEnter}
42+
onMouseLeave={handleMouseLeave}
43+
>
44+
<span className="discount-badge">{discount}%</span>
45+
<img src={images[currentImageIndex]} alt="Product" className="product-image" />
46+
</div>
47+
<div className="product-info">
48+
<div className="product-add">
49+
<div className="icon-container"><PiShoppingCartThin className="icon" /></div>
50+
<div className="icon-container"><CiHeart className="icon" /></div>
51+
</div>
52+
<div className="product-name">{name}</div>
53+
<div className="product-details">
54+
<p className="product-price">{price}</p>
55+
<p className="product-stock"><span className="stock">Stock:</span>{stock}</p>
56+
</div>
57+
<p className="product-description">{truncateDescription(description, 20)}</p>
58+
</div>
59+
</div>
60+
);
61+
};
62+
63+
export default Product;

0 commit comments

Comments
 (0)