Compare commits
2 Commits
7e3c2cf24a
...
1e9e2445e6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e9e2445e6 | ||
|
|
cdc70e9c36 |
@ -44,6 +44,7 @@
|
|||||||
"react-hook-form": "^7.56.1",
|
"react-hook-form": "^7.56.1",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"sonner": "^2.0.3",
|
"sonner": "^2.0.3",
|
||||||
|
"swiper": "^11.2.6",
|
||||||
"tailwind-merge": "^3.2.0",
|
"tailwind-merge": "^3.2.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"tailwindcss-animated": "^2.0.0",
|
"tailwindcss-animated": "^2.0.0",
|
||||||
|
|||||||
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
@ -110,6 +110,9 @@ importers:
|
|||||||
sonner:
|
sonner:
|
||||||
specifier: ^2.0.3
|
specifier: ^2.0.3
|
||||||
version: 2.0.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 2.0.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
swiper:
|
||||||
|
specifier: ^11.2.6
|
||||||
|
version: 11.2.6
|
||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^3.2.0
|
specifier: ^3.2.0
|
||||||
version: 3.2.0
|
version: 3.2.0
|
||||||
@ -2640,6 +2643,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
swiper@11.2.6:
|
||||||
|
resolution: {integrity: sha512-8aXpYKtjy3DjcbzZfz+/OX/GhcU5h+looA6PbAzHMZT6ESSycSp9nAjPCenczgJyslV+rUGse64LMGpWE3PX9Q==}
|
||||||
|
engines: {node: '>= 4.7.0'}
|
||||||
|
|
||||||
tailwind-merge@3.2.0:
|
tailwind-merge@3.2.0:
|
||||||
resolution: {integrity: sha512-FQT/OVqCD+7edmmJpsgCsY820RTD5AkBryuG5IUqR5YQZSdj5xlH5nLgH7YPths7WsLPSpSBNneJdM8aS8aeFA==}
|
resolution: {integrity: sha512-FQT/OVqCD+7edmmJpsgCsY820RTD5AkBryuG5IUqR5YQZSdj5xlH5nLgH7YPths7WsLPSpSBNneJdM8aS8aeFA==}
|
||||||
|
|
||||||
@ -5314,6 +5321,8 @@ snapshots:
|
|||||||
|
|
||||||
supports-preserve-symlinks-flag@1.0.0: {}
|
supports-preserve-symlinks-flag@1.0.0: {}
|
||||||
|
|
||||||
|
swiper@11.2.6: {}
|
||||||
|
|
||||||
tailwind-merge@3.2.0: {}
|
tailwind-merge@3.2.0: {}
|
||||||
|
|
||||||
tailwindcss-animate@1.0.7(tailwindcss@4.1.4):
|
tailwindcss-animate@1.0.7(tailwindcss@4.1.4):
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Handshake } from 'lucide-react';
|
import { Handshake } from 'lucide-react';
|
||||||
import Image from 'next/image';
|
import { useMemo } from 'react';
|
||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
import { Partners } from '@/app/api-utlities/@types';
|
import { Partners } from '@/app/api-utlities/@types';
|
||||||
|
|
||||||
import { useTextController } from '@/shared/language/hooks/use-text-controller';
|
import { useTextController } from '@/shared/language/hooks/use-text-controller';
|
||||||
import { Button } from '@/shared/shadcn-ui/button';
|
import { Button } from '@/shared/shadcn-ui/button';
|
||||||
|
|
||||||
|
import { PartnersSlider } from './partners-slider';
|
||||||
|
|
||||||
interface PartnersSectionProps {
|
interface PartnersSectionProps {
|
||||||
partners: Partners;
|
partners: Partners;
|
||||||
}
|
}
|
||||||
@ -16,9 +17,19 @@ interface PartnersSectionProps {
|
|||||||
export const PartnersSection = ({ partners }: PartnersSectionProps) => {
|
export const PartnersSection = ({ partners }: PartnersSectionProps) => {
|
||||||
const { t } = useTextController();
|
const { t } = useTextController();
|
||||||
|
|
||||||
|
const [partnersFirstHalf, partnersSecondHalf] = useMemo(() => {
|
||||||
|
const length = partners.length;
|
||||||
|
const midPoint = Math.floor(length / 2);
|
||||||
|
|
||||||
|
const partnersFirstHalf = partners.slice(0, midPoint);
|
||||||
|
const partnersSecondHalf = partners.slice(midPoint);
|
||||||
|
|
||||||
|
return [partnersFirstHalf, partnersSecondHalf];
|
||||||
|
}, [partners]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id='partners' className='bg-gray-50 px-2 py-8 sm:py-16'>
|
<section id='partners' className='bg-gray-50 py-8 sm:py-16'>
|
||||||
<div className='container mx-auto'>
|
<div className='mx-auto'>
|
||||||
<div className='mb-12 flex flex-col items-center justify-center text-center'>
|
<div className='mb-12 flex flex-col items-center justify-center text-center'>
|
||||||
<div className='mb-4 inline-flex items-center justify-center rounded-full bg-red-100 p-2'>
|
<div className='mb-4 inline-flex items-center justify-center rounded-full bg-red-100 p-2'>
|
||||||
<Handshake className='h-6 w-6 text-red-600' />
|
<Handshake className='h-6 w-6 text-red-600' />
|
||||||
@ -31,27 +42,17 @@ export const PartnersSection = ({ partners }: PartnersSectionProps) => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='grid grid-cols-2 gap-4 sm:gap-8 md:grid-cols-4'>
|
<PartnersSlider
|
||||||
{partners.map(({ id, name, poster }) => (
|
partners={partnersFirstHalf}
|
||||||
<div
|
autoplaySpeed={3000}
|
||||||
key={id}
|
className='mb-12'
|
||||||
className='flex h-32 flex-col items-center justify-center gap-0.5 rounded-lg bg-white p-6 shadow-md transition-transform hover:scale-105'
|
/>
|
||||||
data-aos='flip-left'
|
|
||||||
>
|
<PartnersSlider
|
||||||
<Image
|
partners={partnersSecondHalf}
|
||||||
src={
|
autoplaySpeed={4000}
|
||||||
poster ??
|
direction='rtl'
|
||||||
`/placeholder.svg?height=80&width=160&text=Partner ${id}`
|
|
||||||
}
|
|
||||||
alt={`Partner ${id}`}
|
|
||||||
width={160}
|
|
||||||
height={80}
|
|
||||||
className='max-h-16 w-auto'
|
|
||||||
/>
|
/>
|
||||||
<h4 className='font-extralight'>{name}</h4>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='mt-12 text-center'>
|
<div className='mt-12 text-center'>
|
||||||
<h3 className='mb-4 text-xl font-bold'>
|
<h3 className='mb-4 text-xl font-bold'>
|
||||||
@ -60,11 +61,9 @@ export const PartnersSection = ({ partners }: PartnersSectionProps) => {
|
|||||||
<p className='mx-auto mb-6 max-w-2xl text-gray-600'>
|
<p className='mx-auto mb-6 max-w-2xl text-gray-600'>
|
||||||
{t('home.partners.becomePartnerText')}
|
{t('home.partners.becomePartnerText')}
|
||||||
</p>
|
</p>
|
||||||
<Link href='#'>
|
|
||||||
<Button className='bg-red-600 hover:bg-red-700'>
|
<Button className='bg-red-600 hover:bg-red-700'>
|
||||||
{t('common.buttons.contactUs')}
|
{t('common.buttons.contactUs')}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
75
src/widgets/partners-slider.tsx
Normal file
75
src/widgets/partners-slider.tsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Image from 'next/image';
|
||||||
|
// Import Swiper styles
|
||||||
|
import 'swiper/css';
|
||||||
|
import { Autoplay, FreeMode } from 'swiper/modules';
|
||||||
|
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
|
|
||||||
|
import { Partners } from '@/app/api-utlities/@types';
|
||||||
|
|
||||||
|
interface PartnersSliderProps {
|
||||||
|
partners: Partners;
|
||||||
|
autoplaySpeed?: number;
|
||||||
|
className?: string;
|
||||||
|
direction?: 'ltr' | 'rtl';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PartnersSlider({
|
||||||
|
partners,
|
||||||
|
autoplaySpeed = 3000,
|
||||||
|
className = '',
|
||||||
|
direction = 'ltr',
|
||||||
|
}: PartnersSliderProps) {
|
||||||
|
return (
|
||||||
|
<div className={`w-full ${className}`}>
|
||||||
|
<Swiper
|
||||||
|
modules={[Autoplay, FreeMode]} // Register Swiper modules
|
||||||
|
slidesPerView='auto'
|
||||||
|
spaceBetween={30}
|
||||||
|
loop={true}
|
||||||
|
freeMode={true}
|
||||||
|
speed={autoplaySpeed}
|
||||||
|
grabCursor={true}
|
||||||
|
autoplay={{
|
||||||
|
delay: 1000,
|
||||||
|
disableOnInteraction: false,
|
||||||
|
pauseOnMouseEnter: false,
|
||||||
|
reverseDirection: direction === 'rtl',
|
||||||
|
}}
|
||||||
|
allowTouchMove={true}
|
||||||
|
breakpoints={{
|
||||||
|
320: {
|
||||||
|
slidesPerView: 2,
|
||||||
|
spaceBetween: 5,
|
||||||
|
},
|
||||||
|
640: {
|
||||||
|
slidesPerView: 3,
|
||||||
|
spaceBetween: 20,
|
||||||
|
},
|
||||||
|
768: {
|
||||||
|
slidesPerView: 4,
|
||||||
|
spaceBetween: 30,
|
||||||
|
},
|
||||||
|
1024: {
|
||||||
|
slidesPerView: 5,
|
||||||
|
spaceBetween: 30,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{partners.map((partner) => (
|
||||||
|
<SwiperSlide key={partner.id}>
|
||||||
|
<div className='flex h-32 items-center justify-center px-4'>
|
||||||
|
<Image
|
||||||
|
src={partner.poster || '/placeholder.svg'}
|
||||||
|
alt={partner.name}
|
||||||
|
fill
|
||||||
|
className='w-auto scale-90 object-contain transition-transform hover:scale-105'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SwiperSlide>
|
||||||
|
))}
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user