Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shop homepage redesign #208

Merged
merged 40 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
bd38b4e
added embla carousal
Joe-Mwangi Jun 21, 2024
39afc70
banner styles
Joe-Mwangi Jun 21, 2024
a9539a0
added banner
Joe-Mwangi Jun 21, 2024
8b98e20
lazy load img
Joe-Mwangi Jun 22, 2024
b21138d
faq update
Joe-Mwangi Jun 22, 2024
061a84d
carticon
Joe-Mwangi Jun 22, 2024
9e7a411
search design
Joe-Mwangi Jun 22, 2024
7785083
sort design
Joe-Mwangi Jun 22, 2024
09b84d1
filter section design
Joe-Mwangi Jun 22, 2024
9b04413
fixed mobile responsiveness
Joe-Mwangi Jun 22, 2024
1d620b4
section wrapper
Joe-Mwangi Jun 22, 2024
25523c1
updated category filter
Joe-Mwangi Jun 23, 2024
8144fd4
sort functionality
Joe-Mwangi Jun 23, 2024
4e7bc06
updated search
Joe-Mwangi Jun 23, 2024
a3afe23
added items page
Joe-Mwangi Jun 23, 2024
a4ad36b
updated itemheader
Joe-Mwangi Jun 23, 2024
f79544c
shoplink update
Joe-Mwangi Jun 23, 2024
47c1e6b
featured products design
Joe-Mwangi Jun 24, 2024
18685e0
added product card
Joe-Mwangi Jun 24, 2024
9d84bdb
updated categories data
Joe-Mwangi Jun 24, 2024
118e729
helper fns
Joe-Mwangi Jun 24, 2024
8eb83d9
new products section
Joe-Mwangi Jun 24, 2024
4579181
rm unused imprts
Joe-Mwangi Jun 24, 2024
af0abb8
query categoires
Joe-Mwangi Jun 24, 2024
6061197
rm hover on mobile
Joe-Mwangi Jun 25, 2024
06fece2
rm query category
Joe-Mwangi Jun 27, 2024
0ce8cd1
carticon update
Joe-Mwangi Jul 9, 2024
7a62eb0
filter items update
Joe-Mwangi Jul 9, 2024
4b60eef
rm packages on banner carousal
Joe-Mwangi Jul 9, 2024
78f650a
css update
Joe-Mwangi Jul 9, 2024
955b0a2
popular prods
Joe-Mwangi Jul 9, 2024
347f343
carousal featured prods
Joe-Mwangi Jul 9, 2024
7c93420
update
Joe-Mwangi Jul 9, 2024
9dc4533
fix link
Joe-Mwangi Jul 9, 2024
20029fc
Merge branch 'Dev' into shop-homepage-redesign
Joe-Mwangi Jul 9, 2024
391ffe2
update css
Joe-Mwangi Jul 9, 2024
9f87d9d
rm unused packages
Joe-Mwangi Jul 9, 2024
cb49191
update link
Joe-Mwangi Jul 9, 2024
cb80712
Merge branch 'Dev' into shop-homepage-redesign
Joe-Mwangi Jul 9, 2024
3ac97f0
updated product section
Joe-Mwangi Jul 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"date-fns": "^2.30.0",
"embla-carousel": "^8.1.5",
"embla-carousel-autoplay": "^8.1.5",
"embla-carousel-react": "^8.1.5",
sonylomo marked this conversation as resolved.
Show resolved Hide resolved
"html-react-parser": "^5.0.6",
"lucide-react": "^0.395.0",
"million": "^3.0.2",
Expand Down
12 changes: 4 additions & 8 deletions src/components/FAQ.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
import { FaChevronDown, FaChevronUp } from "react-icons/fa";
import { useState } from "react";

import { questions } from "../pages/landingPage/data";

function FAQ() {
function FAQ({ questions }) {
const [activeQuestion, setActiveQuestion] = useState(null);

const toggleQuestion = (index) => {
Expand All @@ -16,14 +14,12 @@ function FAQ() {
{questions.map((question, index) => (
<div
key={question.id}
className={`rounded-xl bg-white ${
activeQuestion === index && "mb-4"
}`}
className={`rounded-xl bg-white border shadow-sm mb-4 p-4 `}
>
<h2 className="mb-4 font-semibold" id={`flush-heading${index + 1}`}>
<button
aria-label={question.question}
className={`group relative flex w-full items-center rounded-none border-0 py-4 px-5 text-left text-base transition ${
className={`group relative flex w-full items-center rounded-none border-0 text-left text-base transition ${
activeQuestion === index
? ""
: "overflow-anchor:none hover:z-[2] focus:z-[3]"
Expand Down Expand Up @@ -63,7 +59,7 @@ function FAQ() {
aria-labelledby={`flush-heading${index + 1}`}
data-te-parent="#accordionFlushExample"
>
<div className="py-4 px-5">{question.answer}</div>
<div className=" ">{question.answer}</div>
</div>
</div>
))}
Expand Down
10 changes: 5 additions & 5 deletions src/components/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ const navLinks = [
link: "Resources",
route: "/resources",
},
// {
// id: 7,
// link: "Shop",
// route: "/shop",
// },
{
id: 7,
link: "Shop",
route: "/shop",
},
// {
// id: 8,
// link: "Donate",
Expand Down
17 changes: 17 additions & 0 deletions src/components/shop/CartIcon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { MdAddShoppingCart } from "react-icons/md";
import SectionWrapper from "./SectionWrapper";

const CartIcon = () => {
return (
<SectionWrapper>
<div className="flex justify-end ">
<div className="w-14 md:w-16 h-14 md:h-16 rounded-full p-1 bg-white border shadow-lg cursor-pointer">
<div className="flex w-full h-full rounded-full justify-center items-center bg-green-dark">
<MdAddShoppingCart color="white" size={30} />
</div>
</div>
</div>
</SectionWrapper>
);
};
export default CartIcon;
63 changes: 63 additions & 0 deletions src/components/shop/ProductCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { addCommaSeparator, categoryColors, cn } from "@/utilities/utils";
import { CiShoppingTag } from "react-icons/ci";
import { MdAddShoppingCart } from "react-icons/md";
import { LazyLoadImage } from "react-lazy-load-image-component";
import { Link } from "react-router-dom";

const ProductCard = ({ product }) => {
const { backgroundColor, color } = categoryColors(product.category);

return (
<div className="border rounded-lg p-2.5 pr-1.5 shadow-sm group hover:bg-green-dark/10 bg-white flex flex-col gap-4 ">
<Link
to={`/shop/item/${product.id}`}
className="aspect-h-1 aspect-w-1 w-full bg-gray-200 lg:aspect-none group-hover:opacity-75 lg:h-96"
>
<LazyLoadImage
src={product.image}
alt="Product image"
className="w-full h-80 object-cover object-center lg:h-full lg:w-full"
/>
</Link>
<Link
to={`/shop/item/${product.id}`}
className="flex justify-between pr-1"
>
<h3 className="text-md uppercase font-bold text-gray-600">
{product.name}
</h3>
<div className="p-1 rounded-xl bg-green-dark/10">
{product.stock > 0 ? (
<p className="text-green-dark font-medium text-sm px-1">
<span> {product.stock}</span>
<span className="ml-2">items left</span>
</p>
) : (
<div className=" text-red-800 p-1 rounded-lg bg-red-800/20 font-bold text-base">
<p>Out of stock</p>
</div>
)}
</div>
</Link>
<div className="flex justify-start w-full">
<div
style={{ backgroundColor, color }}
className="px-2 rounded-2xl flex gap-2 items-center"
>
<CiShoppingTag size={28} />
<p className="font-medium text-sm">{product.category}</p>
</div>
</div>
<div className="flex justify-between pr-1">
<h3 className="text-lg font-bold text-gray-700">
KES {addCommaSeparator(Number(product.price))}
</h3>
<div className="flex text-green-dark gap-2 items-center md:opacity-0 md:group-hover:opacity-100 transition-opacity cursor-pointer">
<MdAddShoppingCart size={20} />
<p className="font-bold text-base">Add to cart</p>
</div>
</div>
</div>
);
};
export default ProductCard;
36 changes: 36 additions & 0 deletions src/components/shop/SearchInput.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useState } from "react";
import { IoMdSearch } from "react-icons/io";
import { useNavigate } from "react-router-dom";

const SearchInput = () => {
const [searchText, setSearchText] = useState("");
const navigate = useNavigate();

function handleSubmit(e) {
e.preventDefault();
navigate(`/shop/items?search=${searchText}`);
}

return (
<form
onSubmit={handleSubmit}
className="flex justify-between w-full relative "
>
<input
type="text"
placeholder="Search item"
className="rounded-l-lg pl-16 text-sm shadow-sm w-full border outline-none py-3 text-gray-600 "
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
/>
<IoMdSearch className="absolute top-3 left-8 text-gray-400 " size={24} />
<button
type="submit"
className="text-white text-sm bg-gradient-to-b to-primary from-green-dark py-2 px-4 md:px-20 rounded-r-lg"
>
Search
</button>
</form>
);
};
export default SearchInput;
4 changes: 4 additions & 0 deletions src/components/shop/SectionWrapper.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const SectionWrapper = ({ children }) => {
return <div className="px-4 md:px-10 lg:px-20 my-2 md:my-4">{children}</div>;
};
export default SectionWrapper;
41 changes: 41 additions & 0 deletions src/components/shop/SortItems.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { IoFilter } from "react-icons/io5";
import { Menu } from "@headlessui/react";
import { Link, useLocation } from "react-router-dom";

const SortItems = () => {
const { pathname } = useLocation();
const path = pathname.includes("category") ? pathname : "/shop/items";

return (
<div className="flex flex-col gap-4 relative">
<Menu>
<Menu.Button className="rounded-lg border shadow-sm py-2 px-4 flex gap-2">
<IoFilter size={20} className="text-gray-400" />
<p className="text-sm text-gray-500"> Sort</p>
</Menu.Button>
<Menu.Items
anchor="bottom"
className="absolute top-10 z-10 right-0 w-48 bg-white py-2 px-4 rounded-md flex flex-col gap-2 border shadow-sm"
>
<Menu.Item>
<Link
to={`${path}?sort=low`}
className="text-sm p-2 text-gray-500 cursor-pointer hover:text-green-dark"
>
<p>Lowest price first</p>
</Link>
</Menu.Item>
<Menu.Item>
<Link
to={`${path}?sort=high`}
className="text-sm p-2 text-gray-500 cursor-pointer hover:text-green-dark"
>
<p>Highest price first</p>
</Link>
</Menu.Item>
</Menu.Items>
</Menu>
</div>
);
};
export default SortItems;
2 changes: 1 addition & 1 deletion src/hooks/Queries/shop/useSwagList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ const useSingleSwag = (id) =>
refetchOnWindowFocus: false,
});

export { useSwagList, useSingleSwag };
export { useSwagList, useSingleSwag };
74 changes: 50 additions & 24 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { lazy } from "react";
const AboutUs = lazy(() => import("./pages/aboutUs/AboutUs"));
const AdminLayout = lazy(() => import("./components/admin/AdminLayout"));
const AllBlogsPage = lazy(() => import("./pages/admin/blogs/AllBlogsPage"));
const AddChapterPage = lazy(() =>
import("./pages/admin/chapters/AddChapterPage")
const AddChapterPage = lazy(
() => import("./pages/admin/chapters/AddChapterPage")
);
const AllChaptersPage = lazy(() =>
import("./pages/admin/chapters/AllChaptersPage")
const AllChaptersPage = lazy(
() => import("./pages/admin/chapters/AllChaptersPage")
);
const AddEventPage = lazy(() => import("./pages/admin/events/AddEventPage"));
const AllEventsPage = lazy(() => import("./pages/admin/events/AllEventsPage"));
const UpdateEventPage = lazy(() =>
import("./pages/admin/events/UpdateEventPage")
const UpdateEventPage = lazy(
() => import("./pages/admin/events/UpdateEventPage")
);
const ForgotPassword = lazy(() => import("./pages/auth/ForgotPassword"));
const LogIn = lazy(() => import("./pages/auth/LogIn"));
Expand All @@ -23,25 +23,26 @@ const SignUp = lazy(() => import("./pages/auth/SignUp"));
const Blog = lazy(() => import("./pages/blog/Blog"));
const Blog2 = lazy(() => import("./pages/blog2/Blog2"));
const Blogs = lazy(() => import("./pages/blogs/Blogs"));
const IndividualChapter = lazy(() =>
import("./pages/chapter/pages/IndividualChapter")
const IndividualChapter = lazy(
() => import("./pages/chapter/pages/IndividualChapter")
);
const CommunityPage = lazy(() => import("./pages/community/CommunityPage"));
const SingleEvent = lazy(() =>
import("./pages/community/sections/eventsPreview/SingleEvents/SingleEvent")
const SingleEvent = lazy(
() =>
import("./pages/community/sections/eventsPreview/SingleEvents/SingleEvent")
);
const DonatePage = lazy(() => import("./pages/donate/DonatePage"));
const SingleProductDonation = lazy(() =>
import("./pages/donate/pages/SingleProductDonatePage")
const SingleProductDonation = lazy(
() => import("./pages/donate/pages/SingleProductDonatePage")
);
const Error400 = lazy(() => import("./pages/errorPages/Error400"));
const Error403 = lazy(() => import("./pages/errorPages/Error403"));
const Error404 = lazy(() => import("./pages/errorPages/Error404"));
const Error500 = lazy(() => import("./pages/errorPages/Error500"));
const ErrorBoundary = lazy(() => import("./pages/errorPages/ErrorBoundary"));
const EventsPage = lazy(() => import("./pages/events/pages/EventsPage"));
const EventsSection = lazy(() =>
import("./pages/events/sections/eventsSection/EventsSection")
const EventsSection = lazy(
() => import("./pages/events/sections/eventsSection/EventsSection")
);
const GalleryPage = lazy(() => import("./pages/gallery/GalleryPage"));
const LandingPage = lazy(() => import("./pages/landingPage/LandingPage"));
Expand All @@ -51,27 +52,52 @@ const Resources = lazy(() => import("./pages/resources/Resources"));
const Homepage = lazy(() => import("./pages/shop/Homepage"));
const Checkout = lazy(() => import("./pages/shop/OrderSummaryPage"));
const ProductDisplay = lazy(() => import("./pages/shop/ProductDisplayPage"));
const CategoriesProducts = lazy(() =>
import("./pages/shop/sections/CategoriesProducts")
const CategoriesProducts = lazy(
() => import("./pages/shop/sections/CategoriesProducts")
);
const AllProducts = lazy(() => import("./pages/shop/sections/AllProducts"));
const SingleItemPage = lazy(() => import("./pages/shop/SingleItemPage"));

const ShopDashboard = lazy(() => import("./pages/admin/shop/ShopDashboard"));

export {
AboutUs, AddChapterPage,
AllProducts,
AboutUs,
AddChapterPage,
AddEventPage,
AdminLayout,
AllBlogsPage,
AllChaptersPage,
AllEventsPage, Blog,
Blog2, Blogs, CategoriesProducts, Checkout, CommunityPage,
DonatePage, Error400,
AllEventsPage,
Blog,
Blog2,
Blogs,
CategoriesProducts,
Checkout,
CommunityPage,
DonatePage,
Error400,
Error403,
Error404,
Error500,
ErrorBoundary, EventsPage,
EventsSection, ForgotPassword, GalleryPage, Homepage, IndividualChapter, LandingPage, Layout, LogIn, ProductDisplay, Products, ResetPassword, Resources, ShopDashboard,
SignUp, SingleEvent, SingleItemPage, SingleProductDonation, UpdateEventPage
ErrorBoundary,
EventsPage,
EventsSection,
ForgotPassword,
GalleryPage,
Homepage,
IndividualChapter,
LandingPage,
Layout,
LogIn,
ProductDisplay,
Products,
ResetPassword,
Resources,
ShopDashboard,
SignUp,
SingleEvent,
SingleItemPage,
SingleProductDonation,
UpdateEventPage,
};

3 changes: 2 additions & 1 deletion src/pages/landingPage/sections/FaqSection.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";

import { FAQ } from "../../../components";
import { questions } from "../data";

function FaqSection() {
return (
Expand All @@ -17,7 +18,7 @@ function FaqSection() {
</p>
</div>

<FAQ />
<FAQ questions={questions} />
</section>
);
}
Expand Down
Loading
Loading