Skip to content

Commit ecd3973

Browse files
authored
Merge branch 'staging' into DY-9-fix
2 parents 7ebebde + bf1aece commit ecd3973

25 files changed

Lines changed: 973 additions & 27 deletions

app/(home)/components/Sponsors.tsx

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Container } from '@/components/ui/container';
2+
import dynamic from 'next/dynamic';
3+
const SponsorsDesktop = dynamic(() => import('./SponsorsDesktop'));
4+
const SponsorsMobile = dynamic(() => import('./SponsorsMobile'));
5+
6+
interface SponsorshipProps {
7+
name: string;
8+
logo: string;
9+
logoMobile: string;
10+
description: string;
11+
url: string;
12+
}
13+
14+
export function Sponsors() {
15+
const sponsors: SponsorshipProps[] = [
16+
{
17+
name: 'Mugna Tech',
18+
logo: '/sponsor-logos/mugna-logo.png',
19+
logoMobile: '/sponsor-logos/mugna-logo.png',
20+
description:
21+
'Mugna Tech specializes in Web, Software, and Mobile Development, UI/UX Design, and more, with 75+ projects for diverse businesses.',
22+
url: 'https://mugna.tech',
23+
},
24+
{
25+
name: 'Codev',
26+
logo: '/sponsor-logos/codev-logo.png',
27+
logoMobile: '/sponsor-logos/codev-logo.png',
28+
description:
29+
'Hire top offshore developers with CoDev—skilled professionals dedicated to your success.',
30+
url: 'https://codev.com',
31+
},
32+
{
33+
name: 'Ingenuity Software',
34+
logo: '/sponsor-logos/ingenuity-logo.png',
35+
logoMobile: '/sponsor-logos/ingenuity-logo-mobile.png',
36+
description:
37+
'Ingenuity Software is a Davao-based software development company that turns ideas into impactful digital solutions. ',
38+
url: 'https://ingenuity.ph',
39+
},
40+
{
41+
name: 'PythonPH',
42+
logo: '/sponsor-logos/pythonph-logo.png',
43+
logoMobile: '/sponsor-logos/pythonph-logo-mobile.png',
44+
description:
45+
'Python Philippines is a volunteer-run non-profit supporting the growth of the Python community in the country.',
46+
url: 'https://python.ph',
47+
},
48+
{
49+
name: 'Stace',
50+
logo: '/sponsor-logos/stace-logo.svg',
51+
logoMobile: '/sponsor-logos/stace-logo.svg',
52+
description:
53+
'Stace is a comprehensive platform designed to enhance and simplify the rental experience for both renters and landlords.',
54+
url: 'https://www.stace.app',
55+
},
56+
];
57+
58+
return (
59+
<section className="bg-[#112018] py-16 font-montserrat lg:mb-[-90px] md:mb-[-70px] sm:mb-0">
60+
<Container>
61+
{/* Desktop View (768px and up) */}
62+
<section className="hidden md:block">
63+
<SponsorsDesktop sponsors={sponsors} />
64+
</section>
65+
66+
{/* Mobile View (Below 768px) */}
67+
<section className="md:hidden">
68+
<SponsorsMobile sponsors={sponsors} />
69+
</section>
70+
</Container>
71+
</section>
72+
);
73+
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
'use client';
2+
3+
import { useEffect, useState, useRef } from 'react';
4+
import { cn } from '@/lib/utils';
5+
import Autoplay from 'embla-carousel-autoplay';
6+
import {
7+
Carousel,
8+
CarouselApi,
9+
CarouselContent,
10+
CarouselItem,
11+
CarouselNext,
12+
CarouselPrevious,
13+
} from '@/components/ui/carousel';
14+
import Image from 'next/image';
15+
import Link from 'next/link';
16+
import { Button } from '@/components/ui/button';
17+
18+
interface SponsorshipProps {
19+
name: string;
20+
logo: string;
21+
logoMobile: string;
22+
description: string;
23+
url: string;
24+
}
25+
26+
const SponsorsDesktop = ({ sponsors }: { sponsors: SponsorshipProps[] }) => {
27+
const [api, setApi] = useState<CarouselApi>();
28+
const [current, setCurrent] = useState(0);
29+
const [count, setCount] = useState(0);
30+
31+
// State to hold the featured sponsor
32+
const [featuredSponsor, setfeaturedSponsor] = useState<SponsorshipProps>(
33+
sponsors[0]
34+
);
35+
36+
useEffect(() => {
37+
if (!api) {
38+
return;
39+
}
40+
setCount(api.scrollSnapList().length);
41+
42+
// Set the current index to the first item
43+
api.scrollTo(2);
44+
45+
api.on('select', () => {
46+
const currentIndex = api.selectedScrollSnap();
47+
const correctedCurrentIndex = (currentIndex + 3) % sponsors.length;
48+
setCurrent(correctedCurrentIndex);
49+
setfeaturedSponsor(sponsors[correctedCurrentIndex]);
50+
});
51+
}, [api, sponsors]);
52+
53+
const plugin = useRef(Autoplay({ delay: 5000, stopOnInteraction: true }));
54+
55+
const autoPlayInteraction = () => {
56+
plugin.current.stop();
57+
// Wait for 5 seconds before resuming autoplay but when the user clicks it cancel the autoplay
58+
setTimeout(() => {
59+
if (api) {
60+
plugin.current.play();
61+
}
62+
}, 5000);
63+
};
64+
65+
const carouselFeaturedAnimation = (
66+
sponsor: SponsorshipProps,
67+
index: number
68+
) => {
69+
setfeaturedSponsor(sponsor);
70+
api?.scrollTo(index + 2);
71+
updateButton(index);
72+
autoPlayInteraction();
73+
};
74+
75+
const updateButton = (index: number) => {
76+
setCurrent(index);
77+
api?.scrollTo(index + 2);
78+
setfeaturedSponsor(sponsors[index]);
79+
autoPlayInteraction();
80+
};
81+
82+
return (
83+
<div className="xl:grid xl:grid-cols-[1fr_2fr] md:flex md:flex-col md:h-auto text-white gap-x-8 py-16 items-center ">
84+
{/* Description Section */}
85+
<div className="space-y-16 xl:mb-28 lg:flex-1 lg:h-auto md:flex-1 md:h-auto w-[480px]">
86+
<div className="space-y-9 xl:mx-0">
87+
<h1 className="text-primary text-[80px] leading-none font-bold mb-12">
88+
<span className="text-white">Our</span> Sponsors
89+
</h1>
90+
<p className="text-xl text-left mb-12 min-w-10">
91+
A big thank you to our generous sponsors whose support makes our
92+
work possible and helps us create lasting impact.
93+
</p>
94+
<Button
95+
variant={'sponsor-be-our-sponsor'}
96+
onClick={() => {
97+
window.location.href = '/404';
98+
}}
99+
>
100+
Be Our Sponsor
101+
</Button>
102+
</div>
103+
104+
<div className="max-w-[365px] mx-auto">
105+
<div className="relative w-full">
106+
<div className="opacity-40 w-1/2 bg-gradient-to-r from-[#36FF90] to-transparent h-full absolute blur-md"></div>
107+
</div>
108+
</div>
109+
</div>
110+
111+
<div className="pb-36 w-[633px] xl:ml-16">
112+
{/* Featured Section */}
113+
{featuredSponsor && (
114+
<div className="flex-1 h-[418px] mb-4">
115+
<Link
116+
href={featuredSponsor.url}
117+
target="_blank"
118+
className="border border-[#ffffff] rounded-lg xl:px-10 xl:py-4 lg:p-6 w-full h-full flex flex-col justify-center items-center overflow-hidden"
119+
>
120+
<div className="w-full h-[200px] relative flex justify-center items-center transition-transform duration-500 ease-in-out hover:scale-105">
121+
<Image
122+
src={featuredSponsor.logo}
123+
alt={featuredSponsor.name}
124+
loading="lazy"
125+
fill
126+
className={cn(
127+
featuredSponsor.name === 'PythonPH'
128+
? 'scale-150'
129+
: 'scale-100',
130+
'object-contain',
131+
'w-full',
132+
'h-full',
133+
'p-12'
134+
)}
135+
/>
136+
</div>
137+
<div className="h-[50px] w-[480px] flex items-center">
138+
{/* Icon */}
139+
<div className="mr-2">
140+
<svg
141+
xmlns="http://www.w3.org/2000/svg"
142+
width="24"
143+
height="24"
144+
viewBox="0 0 24 20"
145+
fill="white"
146+
stroke="#ffffff"
147+
strokeLinecap="round"
148+
strokeLinejoin="round"
149+
className="lucide lucide-quote-icon lucide-quote text-[#ffffff] transform rotate-180 w-6 h-6"
150+
>
151+
<path d="M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z" />
152+
<path d="M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z" />
153+
</svg>
154+
</div>
155+
{/* Horizontal Line */}
156+
<div className="w-[440px] h-[1.5px] bg-[#FFFFFF]"></div>
157+
</div>
158+
<p className="lg:text-xl mt-4 text-[12px] max-md:m-5 pr-3 pl-3">
159+
{featuredSponsor.description}
160+
<br></br>
161+
<br></br>{featuredSponsor.name}
162+
</p>
163+
</Link>
164+
</div>
165+
)}
166+
167+
{/* Carousel Section */}
168+
<div className="flex-1 h-auto flex relative">
169+
{/*Carousel Body*/}
170+
<Carousel
171+
className="w-full flex h-full"
172+
setApi={setApi}
173+
plugins={[plugin.current]}
174+
opts={{
175+
loop: true,
176+
}}
177+
>
178+
{/* Previous Button */}
179+
<a onClick={autoPlayInteraction}>
180+
<CarouselPrevious className="absolute left-[-64px] z-10 h-16 w-16 sm:w-20 sm:h-20" />
181+
</a>
182+
183+
{/* Carousel Content */}
184+
<CarouselContent>
185+
{sponsors.map((sponsor, index) => (
186+
<CarouselItem key={index} className="basis-1/3">
187+
<div
188+
key={index}
189+
className="relative group transition-all duration-500 col-span-3 row-span-4 ease-in-out h-[166px] w-[200px]
190+
"
191+
onClick={() => carouselFeaturedAnimation(sponsor, index)}
192+
>
193+
{/* Gradient Overlay */}
194+
<div className="absolute inset-0 bg-gradient-to-t from-[#00833A] to-[rgba(62,179,114,0)] opacity-0 transition-opacity duration-500 rounded-lg group-hover:opacity-100"></div>
195+
196+
<div className="border border-[#ffffff] rounded-lg xl:px-6 xl:py-4 lg:p-6 w-full h-full flex justify-center items-center">
197+
{/* Logo Container */}
198+
<div className="min-h-[160px] min-w-[160px] relative flex justify-center items-center transition-transform duration-500 ease-in-out hover:scale-105">
199+
<div className="">
200+
<Image
201+
src={sponsor.logoMobile}
202+
alt={sponsor.name}
203+
loading="lazy"
204+
fill
205+
className={cn(
206+
'object-contain',
207+
sponsor.name === 'PythonPH'
208+
? 'scale-75'
209+
: 'scale-100',
210+
'w-full',
211+
'h-full'
212+
)}
213+
/>
214+
</div>
215+
</div>
216+
</div>
217+
</div>
218+
</CarouselItem>
219+
))}
220+
</CarouselContent>
221+
222+
{/* Next Button */}
223+
<a onClick={autoPlayInteraction}>
224+
<CarouselNext className="absolute right-[-64px] z-10 h-16 w-16 sm:w-20 sm:h-20" />
225+
</a>
226+
</Carousel>
227+
</div>
228+
{/* Dots Navigation */}
229+
<div className="flex justify-center mt-4">
230+
{Array.from({ length: count }).map((_, index) => (
231+
<button
232+
key={index}
233+
onClick={() => updateButton(index)}
234+
className={cn(
235+
'w-3 h-3 rounded-full mx-1',
236+
current === index ? 'bg-primary' : 'bg-gray-400'
237+
)}
238+
></button>
239+
))}
240+
</div>
241+
</div>
242+
</div>
243+
);
244+
};
245+
246+
export default SponsorsDesktop;

0 commit comments

Comments
 (0)