Skip to content

Commit

Permalink
feature: /get-blogs integration
Browse files Browse the repository at this point in the history
  • Loading branch information
prashantsingh181 committed Oct 26, 2024
1 parent 19c82a5 commit 111b188
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 67 deletions.
148 changes: 81 additions & 67 deletions src/components/HeroSection.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import React, { useState, useEffect } from "react";
import useFetch from "../hooks/useFetch";
import Loader from "./loader/Loader";

const HeroSection = ({ posts, autoSlideInterval = 5000 }) => {
const { data: apiPosts, loading, error } = useFetch("/get-blogs");
const postsToDisplay = error || !apiPosts ? posts : apiPosts;
const [currentIndex, setCurrentIndex] = useState(0);

// Function to go to the next post
const handleNextPost = () => {
setCurrentIndex((prevIndex) =>
prevIndex === posts.length - 1 ? 0 : prevIndex + 1
prevIndex === postsToDisplay.length - 1 ? 0 : prevIndex + 1
);
};

// Function to go to the previous post
const handlePrevPost = () => {
setCurrentIndex((prevIndex) =>
prevIndex === 0 ? posts.length - 1 : prevIndex - 1
prevIndex === 0 ? postsToDisplay.length - 1 : prevIndex - 1
);
};

Expand All @@ -25,77 +29,87 @@ const HeroSection = ({ posts, autoSlideInterval = 5000 }) => {
return () => clearInterval(slideInterval);
}, [currentIndex, autoSlideInterval]);

const post = posts[currentIndex];
const post = postsToDisplay[currentIndex];

return (
<div className="pt-20">
<section className="relative bg-gray-900 text-white overflow-hidden transition-all duration-500 ease-in-out">
{/* Background Image */}
<img
src={post.img}
alt={post.title}
className="w-full h-[36rem] object-cover opacity-80 transition-opacity duration-500"
/>

{/* Content Overlay */}
<div className="absolute inset-0 flex items-center md:pl-24 px-3 transition-all duration-500">
<div className="text-center mx-auto md:mx-0 md:text-left max-w-lg">
<span className="text-sm font-medium uppercase text-gray-300">
Featured
</span>
<h1 className="text-2xl sm:text-4xl font-bold leading-tight mt-2 w-4/5 md:w-full mx-auto">
{post.title}
</h1>
<p className="mt-5 sm:mt-4 text-gray-200 w-[85%] mx-auto md:w-full">{post.description}</p>
<button className="px-4 py-2 mt-6 bg-primary text-white rounded-lg duration-200 hover:opacity-90">
Read More
</button>
{loading ? (
<div className="grid place-items-center h-[36rem]">
<Loader />
</div>
) : (
<>
{/* Background Image */}
<img
src={post.img}
alt={post.title}
className="w-full h-[36rem] object-cover opacity-80 transition-opacity duration-500"
/>

{/* Arrow Buttons */}
<div className="absolute left-0 md:left-4 top-1/2 transform -translate-y-1/2">
<button
onClick={handlePrevPost}
className="bg-white text-black p-3 rounded-full"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 sm:h-6 sm:w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15 19l-7-7 7-7"
/>
</svg>
</button>
</div>
<div className="absolute right-0 md:right-4 top-1/2 transform -translate-y-1/2">
<button
onClick={handleNextPost}
className="bg-white text-black p-3 rounded-full"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 sm:h-6 sm:w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 5l7 7-7 7"
/>
</svg>
</button>
</div>
</div>
{/* Content Overlay */}
<div className="absolute inset-0 flex items-center md:pl-24 px-3 transition-all duration-500">
<div className="text-center mx-auto md:mx-0 md:text-left max-w-lg">
<span className="text-sm font-medium uppercase text-gray-300">
Featured
</span>
<h1 className="text-2xl sm:text-4xl font-bold leading-tight mt-2 w-4/5 md:w-full mx-auto">
{post.title}
</h1>
<p className="mt-5 sm:mt-4 text-gray-200 w-[85%] mx-auto md:w-full">
{post.description}
</p>
<button className="px-4 py-2 mt-6 bg-primary text-white rounded-lg duration-200 hover:opacity-90">
Read More
</button>
</div>

{/* Arrow Buttons */}
<div className="absolute left-0 md:left-4 top-1/2 transform -translate-y-1/2">
<button
onClick={handlePrevPost}
className="bg-white text-black p-3 rounded-full"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 sm:h-6 sm:w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15 19l-7-7 7-7"
/>
</svg>
</button>
</div>
<div className="absolute right-0 md:right-4 top-1/2 transform -translate-y-1/2">
<button
onClick={handleNextPost}
className="bg-white text-black p-3 rounded-full"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 sm:h-6 sm:w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 5l7 7-7 7"
/>
</svg>
</button>
</div>
</div>
</>
)}
</section>
</div>
);
Expand Down
9 changes: 9 additions & 0 deletions src/components/loader/Loader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import "./loader.css"

function Loader() {
return (
<div className="loader" />
)
}

export default Loader
18 changes: 18 additions & 0 deletions src/components/loader/loader.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* HTML: <div class="loader"></div> */
.loader {
width: 60px;
aspect-ratio: 2;
--_g: no-repeat radial-gradient(circle closest-side,#fff 90%,#0000);
background:
var(--_g) 0% 50%,
var(--_g) 50% 50%,
var(--_g) 100% 50%;
background-size: calc(100%/3) 50%;
animation: l3 1s infinite linear;
}
@keyframes l3 {
20%{background-position:0% 0%, 50% 50%,100% 50%}
40%{background-position:0% 100%, 50% 0%,100% 50%}
60%{background-position:0% 50%, 50% 100%,100% 0%}
80%{background-position:0% 50%, 50% 50%,100% 100%}
}
29 changes: 29 additions & 0 deletions src/hooks/useFetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useState, useEffect } from "react";

export default function useFetch(url, options) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const json = await response.json();
setData(json);
} catch (error) {
console.error(error);
setError(error.message);
} finally {
setLoading(false);
}
};

fetchData();
}, [url, options]);

return { data, error, loading };
}

0 comments on commit 111b188

Please sign in to comment.