Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion my-brand-nextjs/src/components/atoms/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(

const variants = {
primary:
"bg-[#2f2b2b] border border-[#916868] text-white hover:bg-primary hover:text-[#e0c110] hover:border-yellow-400",
"relative inline-flex items-center gap-3 bg-brand hover:bg-brand-dark text-white font-bold px-10 py-5 rounded-3xl transition-all duration-300 transform hover:scale-105 hover:shadow-2xl hover:shadow-brand/20",
secondary:
"bg-secondary text-white border border-gray-700 hover:border-yellow-400 hover:text-yellow-400",
outline:
Expand Down
9 changes: 2 additions & 7 deletions my-brand-nextjs/src/features/home/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,28 @@ import { getRecentBlogsForHome } from "@/services/blogService";
import { projectsData } from "@/lib/projectData";

export function HomePage() {
// Blog state management
const [blogPosts, setBlogPosts] = useState<any[]>([]);
const [blogLoading, setBlogLoading] = useState(true);

// Fetch recent blogs on component mount with timeout handling
useEffect(() => {
const fetchRecentBlogs = async () => {
setBlogLoading(true);
try {
const blogs = await getRecentBlogsForHome();
setBlogPosts(blogs); // blogs will be empty array if error occurred
setBlogPosts(blogs);
} catch (error) {
// This shouldn't happen since service handles errors gracefully
console.warn('Failed to fetch recent blogs:', error);
setBlogPosts([]); // Fallback to empty array
setBlogPosts([]);
} finally {
setBlogLoading(false);
}
};

// Use setTimeout to prevent blocking initial render
const timeoutId = setTimeout(fetchRecentBlogs, 100);

return () => clearTimeout(timeoutId);
}, []);

// Sample data - in a real app, this would come from an API or CMS
const heroData = {
title: "Crafting Digital Experiences That Matter",
subtitle: "I'm Jean Paul Elisa NIYOKWIZERWA, Full Stack Software Engineer.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ const ContactSection: React.FC<ContactSectionProps> = ({
type="submit"
disabled={isSubmitting}
className={cn(
"w-full group bg-gradient-to-r from-yellow-500 to-yellow-700 hover:from-yellow-500 hover:to-yellow-600 text-black font-semibold px-8 py-4 rounded-2xl transition-all duration-300 transform hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none",
"w-full",
isSubmitting && "animate-pulse"
)}
>
Expand Down
66 changes: 33 additions & 33 deletions my-brand-nextjs/src/features/home/components/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ const Hero: React.FC<HeroProps> = ({
>
{/* Dynamic Background Elements */}
<div className="absolute inset-0 -z-10">
{/* Gradient Overlay */}
<div className="absolute inset-0 bg-gradient-to-br from-gray-50 via-gray-100 to-gray-200 dark:from-primary dark:via-secondary dark:to-primary transition-colors duration-500" />
{/* Solid Overlay */}
<div className="absolute inset-0 bg-gray-50 dark:bg-primary transition-colors duration-500" />

{/* Animated Background Shapes */}
<div className="absolute top-1/4 left-1/4 w-72 h-72 bg-yellow-400/20 dark:bg-yellow-400/5 rounded-full blur-3xl animate-pulse transform transition-all duration-1000" />
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-purple-500/15 dark:bg-purple-500/5 rounded-full blur-3xl animate-pulse transform transition-all duration-1000" />
<div className="absolute top-1/4 left-1/4 w-72 h-72 bg-blue-400/15 dark:bg-blue-400/5 rounded-full blur-3xl animate-pulse transform transition-all duration-1000" />
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-indigo-500/15 dark:bg-indigo-500/5 rounded-full blur-3xl animate-pulse transform transition-all duration-1000" />

{/* Grid Pattern */}
<div className="absolute inset-0 opacity-10 dark:opacity-10 bg-grid-pattern transition-opacity duration-300" />
Expand All @@ -90,17 +90,17 @@ const Hero: React.FC<HeroProps> = ({
{/* Badge/Status Indicator */}
<div
className={cn(
"inline-flex items-center gap-2 bg-yellow-400/20 dark:bg-yellow-400/10 backdrop-blur-sm border border-yellow-400/40 dark:border-yellow-400/20 rounded-full px-4 py-2 text-sm font-medium text-yellow-600 dark:text-yellow-400",
"inline-flex items-center gap-2 bg-blue-500/10 dark:bg-blue-400/10 backdrop-blur-sm border border-blue-500/30 dark:border-blue-400/20 rounded-full px-4 py-2 text-sm font-medium text-blue-700 dark:text-blue-300",
"transform transition-all duration-1000 ease-out",
isVisible
? "translate-y-0 opacity-100"
: "translate-y-8 opacity-0"
)}
>
<div className="w-2 h-2 bg-yellow-500 dark:bg-yellow-400 rounded-full animate-pulse" />
<div className="w-2 h-2 bg-blue-500 dark:bg-blue-400 rounded-full animate-pulse" />
<Typography
variant="small"
className="text-sm font-medium text-yellow-600 dark:text-yellow-400"
className="text-sm font-medium text-blue-700 dark:text-blue-300"
>
Available for new opportunities
</Typography>
Expand Down Expand Up @@ -131,7 +131,7 @@ const Hero: React.FC<HeroProps> = ({
className={cn(
"inline-block mr-3 mb-2",
shouldHighlight
? "text-transparent bg-gradient-to-r from-yellow-500 via-yellow-400 to-yellow-600 dark:from-yellow-400 dark:via-yellow-300 dark:to-yellow-500 bg-clip-text animate-pulse"
? "text-brand dark:text-brand-light"
: "text-gray-800 dark:text-white"
)}
>
Expand All @@ -154,11 +154,11 @@ const Hero: React.FC<HeroProps> = ({
)}
>
{/* Background Elements */}
<div className="absolute -inset-6 bg-gradient-to-r from-yellow-400/30 via-purple-500/20 to-blue-500/30 dark:from-yellow-400/20 dark:via-purple-500/10 dark:to-blue-500/20 rounded-full blur-2xl animate-pulse transition-colors duration-300" />
<div className="absolute -inset-3 bg-gradient-to-r from-yellow-400/50 to-transparent dark:from-yellow-400/30 dark:to-transparent rounded-full blur-xl transition-colors duration-300" />
<div className="absolute -inset-6 bg-brand/10 dark:bg-brand/10 rounded-full blur-2xl transition-colors duration-300" />
<div className="absolute -inset-3 bg-brand/15 dark:bg-brand/15 rounded-full blur-xl transition-colors duration-300" />

{/* Main Image Container */}
<div className="relative w-64 h-64 md:w-80 md:h-80 lg:w-72 lg:h-72 xl:w-80 xl:h-80 rounded-full overflow-hidden border-4 border-gradient-to-r from-yellow-400 via-yellow-300 to-yellow-500 shadow-2xl shadow-yellow-400/40 dark:shadow-yellow-400/25 animate-[bounce_2s_ease-in-out_infinite] transition-shadow duration-300">
<div className="relative w-64 h-64 md:w-80 md:h-80 lg:w-72 lg:h-72 xl:w-80 xl:h-80 rounded-full overflow-hidden border-4 border-brand/40 shadow-2xl shadow-brand/20 transition-shadow duration-300">
{/* Image */}
<Image
src={profileImage}
Expand All @@ -169,24 +169,24 @@ const Hero: React.FC<HeroProps> = ({
/>

{/* Overlay Effects */}
<div className="absolute inset-0 bg-gradient-to-t from-black/30 via-transparent to-transparent dark:from-black/20" />
<div className="absolute inset-0 bg-black/15 dark:bg-black/20" />

{/* Floating Elements */}
<div className="absolute top-4 right-4 w-4 h-4 bg-yellow-500 dark:bg-yellow-400 rounded-full animate-ping" />
<div className="absolute bottom-4 left-4 w-3 h-3 bg-green-500 dark:bg-green-400 rounded-full animate-pulse" />
<div className="absolute top-4 right-4 w-4 h-4 bg-blue-500 dark:bg-blue-400 rounded-full animate-ping" />
<div className="absolute bottom-4 left-4 w-3 h-3 bg-emerald-500 dark:bg-emerald-400 rounded-full animate-pulse" />
</div>
</div>
</div>
</div>

{/* Advanced Bottom Section - Redesigned Layout */}
{/* Advanced Bottom Section*/}
<div className="relative">
{/* Decorative Elements */}
<div className="absolute -top-4 left-1/4 w-32 h-32 bg-yellow-400/20 dark:bg-yellow-400/10 rounded-full blur-2xl transition-colors duration-300" />
<div className="absolute -bottom-4 right-1/4 w-24 h-24 bg-purple-500/15 dark:bg-purple-500/10 rounded-full blur-xl transition-colors duration-300" />
<div className="absolute -top-4 left-1/4 w-32 h-32 bg-blue-400/15 dark:bg-blue-400/10 rounded-full blur-2xl transition-colors duration-300" />
<div className="absolute -bottom-4 right-1/4 w-24 h-24 bg-indigo-500/15 dark:bg-indigo-500/10 rounded-full blur-xl transition-colors duration-300" />

{/* Main Content Grid */}
<div className="relative bg-gradient-to-br from-white/80 via-white/90 to-white/80 dark:from-white/5 dark:via-white/10 dark:to-white/5 backdrop-blur-xl border border-gray-200/30 dark:border-white/10 rounded-3xl p-8 lg:p-12 shadow-2xl transition-colors duration-300">
<div className="relative bg-white/85 dark:bg-white/10 backdrop-blur-xl border border-gray-200/30 dark:border-white/10 rounded-3xl p-8 lg:p-12 shadow-2xl transition-colors duration-300">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 lg:gap-12">
{/* Left Column - Subtitle & Description */}
<div className="lg:col-span-2 space-y-8">
Expand All @@ -201,12 +201,12 @@ const Hero: React.FC<HeroProps> = ({
>
<div className="relative">
{/* Accent Line */}
<div className="absolute -left-6 top-2 w-1 h-16 bg-gradient-to-b from-yellow-500 to-yellow-600 dark:from-yellow-400 dark:to-yellow-600 rounded-full transition-colors duration-300" />
<div className="absolute -left-6 top-2 w-1 h-16 bg-brand dark:bg-brand-light rounded-full transition-colors duration-300" />

<div className="space-y-3">
<Typography
variant="h2"
className="text-2xl md:text-4xl lg:text-5xl font-bold leading-tight text-transparent bg-gradient-to-r from-yellow-500 via-yellow-400 to-yellow-600 dark:from-yellow-400 dark:via-yellow-300 dark:to-yellow-500 bg-clip-text"
className="text-2xl md:text-4xl lg:text-5xl font-bold leading-tight text-brand dark:text-brand-light"
>
{subtitle}
</Typography>
Expand Down Expand Up @@ -237,7 +237,7 @@ const Hero: React.FC<HeroProps> = ({
{description}
</Typography>
{/* Decorative Quote Mark */}
<div className="absolute -top-4 -right-4 text-6xl text-yellow-400/30 dark:text-yellow-400/20 font-serif transition-colors duration-300">
<div className="absolute -top-4 -right-4 text-6xl text-brand/20 dark:text-brand/20 font-serif transition-colors duration-300">
&quot;
</div>
</div>
Expand All @@ -254,14 +254,14 @@ const Hero: React.FC<HeroProps> = ({
>
{primaryCTA && (
<div className="group relative">
{/* Glow Effect */}
<div className="absolute -inset-1 bg-gradient-to-r from-yellow-400 to-yellow-600 rounded-3xl blur opacity-30 group-hover:opacity-50 transition duration-300" />
{/* Solid Glow */}
<div className="absolute -inset-1 bg-brand/20 rounded-3xl blur opacity-30 group-hover:opacity-50 transition duration-300" />

{primaryCTA.download ? (
<a
href={primaryCTA.href}
download
className="relative inline-flex items-center gap-3 bg-gradient-to-r from-yellow-400 to-yellow-500 hover:from-yellow-500 hover:to-yellow-600 text-black font-bold px-10 py-5 rounded-3xl transition-all duration-300 transform hover:scale-105 hover:shadow-2xl hover:shadow-yellow-400/25"
className="relative inline-flex items-center gap-3 bg-brand hover:bg-brand-dark text-white font-bold px-10 py-5 rounded-3xl transition-all duration-300 transform hover:scale-105 hover:shadow-2xl hover:shadow-brand/20"
>
<svg
className="w-6 h-6"
Expand Down Expand Up @@ -292,7 +292,7 @@ const Hero: React.FC<HeroProps> = ({
<Button
variant="outline"
asChild
className="relative border-2 border-gray-300 dark:border-white/30 hover:border-yellow-500 dark:hover:border-yellow-400/70 hover:bg-yellow-400/10 dark:hover:bg-yellow-400/20 text-gray-700 dark:text-white hover:text-yellow-600 dark:hover:text-yellow-300 px-10 py-5 rounded-3xl text-lg font-semibold transition-all duration-300 backdrop-blur-sm"
className="relative border-2 border-gray-300 dark:border-white/30 hover:border-brand dark:hover:border-brand/70 hover:bg-brand/10 dark:hover:bg-brand/20 text-gray-700 dark:text-white hover:text-brand dark:hover:text-brand-light px-10 py-5 rounded-3xl text-lg font-semibold transition-all duration-300 backdrop-blur-sm"
>
<CustomLink href={secondaryCTA.href}>
{secondaryCTA.text}
Expand All @@ -315,14 +315,14 @@ const Hero: React.FC<HeroProps> = ({
)}
>
<div className="relative group">
{/* Animated Border */}
<div className="absolute -inset-1 bg-gradient-to-r from-yellow-400/60 via-purple-500/40 to-blue-500/60 dark:from-yellow-400/50 dark:via-purple-500/30 dark:to-blue-500/50 rounded-2xl blur opacity-30 dark:opacity-20 group-hover:opacity-50 dark:group-hover:opacity-40 transition duration-500" />
{/* Solid Border Accent */}
<div className="absolute -inset-1 bg-brand/10 rounded-2xl blur opacity-30 dark:opacity-20 group-hover:opacity-50 dark:group-hover:opacity-40 transition duration-500" />

<div className="relative p-8 bg-gradient-to-br from-white/90 to-white/70 dark:from-secondary/70 dark:to-secondary/40 backdrop-blur-sm rounded-2xl border border-yellow-400/40 dark:border-yellow-400/30 transition-colors duration-300">
<div className="relative p-8 bg-white/85 dark:bg-secondary/60 backdrop-blur-sm rounded-2xl border border-brand/30 dark:border-brand/30 transition-colors duration-300">
{/* Quote Icon */}
<div className="absolute -top-3 -left-3 w-10 h-10 bg-gradient-to-br from-yellow-400 to-yellow-500 rounded-full flex items-center justify-center shadow-lg">
<div className="absolute -top-3 -left-3 w-10 h-10 bg-brand rounded-full flex items-center justify-center shadow-lg">
<svg
className="w-5 h-5 text-black"
className="w-5 h-5 text-white"
fill="currentColor"
viewBox="0 0 24 24"
>
Expand Down Expand Up @@ -359,7 +359,7 @@ const Hero: React.FC<HeroProps> = ({
>
Connect with me
</Typography>
<div className="w-16 h-1 bg-gradient-to-r from-yellow-500 to-transparent dark:from-yellow-400 dark:to-transparent rounded-full mx-auto lg:mx-0 transition-colors duration-300" />
<div className="w-16 h-1 bg-brand rounded-full mx-auto lg:mx-0 transition-colors duration-300" />
</div>

<div className="flex flex-wrap justify-center lg:justify-start gap-4">
Expand All @@ -368,7 +368,7 @@ const Hero: React.FC<HeroProps> = ({
key={index}
href={social.href}
external
className="group relative p-4 bg-white/80 dark:bg-white/10 backdrop-blur-sm border border-gray-200 dark:border-white/20 rounded-2xl hover:border-yellow-500 dark:hover:border-yellow-400/60 hover:bg-yellow-400/20 dark:hover:bg-yellow-400/20 transition-all duration-300 transform hover:scale-110 hover:-translate-y-2 hover:shadow-xl hover:shadow-yellow-400/25"
className="group relative p-4 bg-white/80 dark:bg-white/10 backdrop-blur-sm border border-gray-200 dark:border-white/20 rounded-2xl hover:border-brand dark:hover:border-brand/60 hover:bg-brand/10 dark:hover:bg-brand/10 transition-all duration-300 transform hover:scale-110 hover:-translate-y-2 hover:shadow-xl hover:shadow-brand/20"
aria-label={social.label}
>
<Image
Expand Down Expand Up @@ -407,7 +407,7 @@ const Hero: React.FC<HeroProps> = ({
<a
href={primaryCTA.href}
download
className="inline-flex items-center gap-2 bg-gradient-to-r from-yellow-400 to-yellow-500 hover:from-yellow-500 hover:to-yellow-600 text-black font-semibold px-6 py-3 rounded-xl transition-all duration-300 transform hover:scale-105"
className="inline-flex items-center gap-2 bg-brand hover:bg-brand-dark text-white font-semibold px-6 py-3 rounded-xl transition-all duration-300 transform hover:scale-105"
>
<svg
className="w-4 h-4"
Expand Down
Loading