Skip to content

Commit

Permalink
Landing Page Hero Section with TailwindCSS, React, TypeScript, and Re…
Browse files Browse the repository at this point in the history
…dux Toolkit
  • Loading branch information
ambroisegithub committed Jun 24, 2024
1 parent a2a61d9 commit 50bcbfc
Show file tree
Hide file tree
Showing 16 changed files with 10,148 additions and 3,609 deletions.
8 changes: 8 additions & 0 deletions .hintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": [
"development"
],
"hints": {
"no-inline-styles": "off"
}
}
13,462 changes: 9,875 additions & 3,587 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
"react-dom": "^18.2.0",
"react-icons": "^5.2.1",
"react-redux": "^9.1.2",
"react-responsive-carousel": "^3.2.23",
"react-router-dom": "^6.23.1",
"redux": "^5.0.1"
},
"devDependencies": {
"@hint/hint-no-inline-styles": "^1.0.18",
"@testing-library/jest-dom": "^6.4.5",
"@testing-library/react": "^16.0.0",
"@types/jsdom": "^21.1.7",
Expand Down
3 changes: 1 addition & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import AppRoutes from './routes/AppRoutes';
import AppRoutes from '@/routes/AppRoutes';

function App() {
return <AppRoutes />;
}

export default App;
18 changes: 0 additions & 18 deletions src/__test__/App.test.tsx

This file was deleted.

75 changes: 75 additions & 0 deletions src/__test__/Hellosection.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { HelloSection } from '@/components/HelloSection/HelloSection'; // Adjust the import path as necessary
import { describe, it, expect } from 'vitest';
import { MemoryRouter } from 'react-router-dom';


describe('HelloSection Component', () => {
it('renders the first slide initially', async () => {
render(
<MemoryRouter>
<HelloSection />
</MemoryRouter>
);

await waitFor(() => {
const images = screen.getAllByAltText('Slide Image');
expect(images[0]).toBeInTheDocument();
expect(screen.getByText('Absolutely hot collections🔥')).toBeInTheDocument();
});
});

it('navigates to the next slide on button click', async () => {
render(
<MemoryRouter>
<HelloSection />
</MemoryRouter>
);

const nextButton = screen.getByRole('button', { name: /next slide/i });
fireEvent.click(nextButton);

await waitFor(() => {
expect(screen.getByText('Exclusive Summer Sale☀️')).toBeInTheDocument();
expect(screen.getByRole('button', { name: /previous slide/i })).toBeEnabled();
});
});

it('navigates to the previous slide on button click', async () => {
render(
<MemoryRouter>
<HelloSection />
</MemoryRouter>
);

const nextButton = screen.getByRole('button', { name: /next slide/i });
fireEvent.click(nextButton);
fireEvent.click(nextButton);

const prevButton = screen.getByRole('button', { name: /previous slide/i });
fireEvent.click(prevButton);

await waitFor(() => {
expect(screen.getByText('Absolutely hot collections🔥')).toBeInTheDocument();
});
});

it('updates the active slide indicator', async () => {
render(
<MemoryRouter>
<HelloSection />
</MemoryRouter>
);

await waitFor(() => {
expect(screen.getByTestId('active-indicator-0')).toHaveClass('bg-[#6D31ED]');

const nextButton = screen.getByRole('button', { name: /next slide/i });
fireEvent.click(nextButton);

expect(screen.getByTestId('active-indicator-1')).toHaveClass('bg-[#6D31ED]');
});
});


});
Binary file added src/assets/welcome.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/welcome1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/welcome2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/components/FrontFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function FrontFooter() {
return <div className="pl-20">Front Footer</div>;
}

export default FrontFooter;
135 changes: 135 additions & 0 deletions src/components/HelloSection/HelloSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React, { useState } from 'react';
import HSButton from '@/components/form/HSButton';
import HelloImage from '@/assets/welcome.jpg';
import HelloImage1 from '@/assets/welcome1.png';
import HelloImage2 from '@/assets/welcome2.png';

import { SlArrowLeft, SlArrowRight } from 'react-icons/sl';

interface SlideProps {
title: string;
mainText: string[];
buttonText: string;
img: string;
}

const slides: SlideProps[] = [
{
title: 'Absolutely hot collections🔥',
mainText: ['The Best Place To', 'Find And Buyer', 'Amazing Product'],
buttonText: 'Shop now!',
img: HelloImage,
},
{
title: 'Exclusive Summer Sale☀️',
mainText: ['Unbeatable Deals', 'On All Your', 'Favorite Items'],
buttonText: 'Discover Now!',
img: HelloImage1,
},
{
title: 'New Arrivals✨',
mainText: ['Fresh Styles', 'Just Landed', 'Shop Today'],
buttonText: 'Explore New!',
img: HelloImage2,
},
];

const Slide: React.FC<{ slide: SlideProps }> = ({ slide }) => (
<div className="w-full h-auto flex flex-col p-5 gap-10 lg:flex-row md:flex-row bg-white">
<div className="w-full pl-0 pt-10 md:w-1/2 flex h-auto flex-col flex-1 lg:pl-10 md:pl-0">
<h2 className="flex justify-center text-[#171A1F] text-[18px] mb-4 lg:justify-start items-start">
{slide.title}
</h2>
<div>
{slide.mainText.map((text, index) => (
<p
key={index}
className="text-[28px] flex justify-center items-center md:text-[40px] font-extrabold lg:justify-start lg:items-start"
>
{index === 2 ? (
<>
<span className="mr-2">{text.split(' ')[0]}</span>
<span className="text-[#15ABFF]">{text.split(' ')[1]}</span>
</>
) : (
text
)}
</p>
))}
</div>
<div className="flex justify-center lg:justify-start">
<HSButton
title={slide.buttonText}
styles="hidden bg-[#6D31ED] w-auto text-white p-3 outline-none rounded-md mt-4 lg:flex md:flex"
/>
</div>
</div>
<div className="lg:w-1/2 md:w-1/2 h-auto flex-1 lg:flex md:flex">
<img src={slide.img} alt="Slide Image" className="h-full" />
</div>
</div>
);

const HelloSection: React.FC = () => {
const [currentIndex, setCurrentIndex] = useState(0);

const handlePrev = () => {
setCurrentIndex((prevIndex) =>
prevIndex === 0 ? slides.length - 1 : prevIndex - 1
);
};

const handleNext = () => {
setCurrentIndex((prevIndex) =>
prevIndex === slides.length - 1 ? 0 : prevIndex + 1
);
};

return (
<div className="relative w-full overflow-hidden">
<div
className="flex transition-transform duration-300 ease-in-out"
style={{ transform: `translateX(-${currentIndex * 100}%)` }}
>
{slides.map((slide, index) => (
<div key={index} className="min-w-full">
<Slide slide={slide} />
</div>
))}
</div>

<div className="flex justify-center lg:justify-start">
<HSButton
title={slides[currentIndex].buttonText}
styles="flex bg-[#6D31ED]] w-auto text-white outline-none rounded-md lg:hidden md:hidden"
/>
</div>

<button
onClick={handlePrev}
className="absolute top-1/2 left-[-10px] transform -translate-y-1/2 p-4 outline-none font-bold text-[20px]"
title="Previous Slide"
>
<SlArrowLeft />
</button>
<button
onClick={handleNext}
className="absolute top-1/2 right-[-10px] transform -translate-y-1/2 p-4 outline-none font-bold text-[20px]"
title="Next Slide"
>
<SlArrowRight />
</button>
<div className="relative bottom-[0] left-1/2 transform -translate-x-1/2 space-x-2 p-5 flex flex-row justify-center items-center">
{slides.map((_, index) => (
<div
key={index}
className={`w-2 h-2 rounded-full ${currentIndex === index ? 'bg-[#6D31ED]' : 'bg-gray-300'}`}
data-testid={`active-indicator-${index}`}
/>
))}
</div>
</div>
);
};

export { HelloSection };
Empty file removed src/components/button
Empty file.
37 changes: 37 additions & 0 deletions src/components/form/HSButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Link } from 'react-router-dom';

interface MyButtonProps {
path?: string;
title: string;
styles?: string;
click?: () => void;
icon?: JSX.Element;
target?: '_blank' | '_self' | '_parent' | '_top';
onChange?: React.ChangeEventHandler<HTMLAnchorElement>;
}

function HSButton({
path,
click,
title,
icon,
styles,
target,
onChange,
}: MyButtonProps) {
return (
<Link
target={target}
type="submit"
onChange={onChange}
rel="noopener noreferrer"
to={path!}
onClick={click}
className={`${styles} bg-primary text-white px-6 py-3 rounded-md flex justify-center items-center gap-2 text-sm hover:text-gray-200 hover:shadow-lg hover:scale-105 transition-all duration-300 ease-in-out`}
>
{title} {icon}
</Link>
);
}

export default HSButton;
10 changes: 9 additions & 1 deletion src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { HelloSection } from '../components/HelloSection/HelloSection';
function Home() {
return <p className="text-blueBg">Welcome to Dynamites E-commerce</p>;
return (
<main className=" relative w-full h-auto p-2 lg:p-10 md:p-10 bg-violeteBg">
<div>
<HelloSection />
</div>
{/* Add more componets as you wish!!! */}
</main>
);
}

export default Home;
Empty file removed src/pages/home
Empty file.
2 changes: 1 addition & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ export default {
},
},
plugins: [],
};
};

0 comments on commit 50bcbfc

Please sign in to comment.