webdlh-net/Views/Components/Home/_Mitra.cshtml

283 lines
12 KiB
Plaintext

<div class="container max-w-6xl mx-auto py-20 px-4">
<div class="flex flex-col md:flex-row items-center md:items-start gap-10">
<!-- Left column -->
<div class="md:w-1/3 md:sticky md:top-24 md:self-start text-center md:text-left" data-aos="fade-right" data-aos-duration="800" data-aos-disable="mobile">
<div class="inline-flex items-center bg-oren text-white px-5 py-2 rounded-full shadow-md mb-6">
<i class="w-5 h-5 mr-2 text-white" data-lucide="medal"></i>
<h2 class="text-sm font-semibold">MITRA KAMI</h2>
</div>
<h3 class="text-2xl md:text-3xl font-bold text-gray-800 mb-6">Mitra of The Year</h3>
<p class="text-gray-600 text-balance mb-8">
Mitra terpilih yang telah memberikan kontribusi luar biasa dan bantuan berkelanjutan dalam mendukung program-program Dinas Lingkungan Hidup DKI Jakarta.
</p>
<div class="flex justify-center md:justify-start space-x-3 mb-8 md:mb-0">
<button id="prev-mitra-btn" class="p-2 rounded-full border border-gray-300 hover:border-orange-500 hover:text-orange-500 transition-colors duration-300">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
<button id="next-mitra-btn" class="p-2 rounded-full border border-gray-300 hover:border-orange-500 hover:text-orange-500 transition-colors duration-300">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</button>
<!-- Dots indicator -->
<div class="flex items-center space-x-1.5 ml-4" id="mitra-dots">
<!-- Dots will be created dynamically -->
</div>
</div>
</div>
<!-- Right column: Mitra cards slider -->
<div class="md:w-2/3 relative" data-aos="fade-left" data-aos-duration="1000" data-aos-disable="mobile">
<div class="overflow-hidden">
<div class="flex transition-all duration-500 ease-out" id="slider-mitra">
<!-- Rows of mitra cards will be rendered here -->
</div>
</div>
</div>
</div>
</div>
<register-block dynamic-section="scripts" key="jsMitra">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
if (window.innerWidth < 768) {
// Disable AOS on mobile
const elements = document.querySelectorAll('[data-aos-disable="mobile"]');
elements.forEach(element => {
element.setAttribute('data-aos', 'none');
});
} else {
// Enable AOS on desktop
const elements = document.querySelectorAll('[data-aos-disable="mobile"]');
elements.forEach(element => {
element.setAttribute('data-aos', 'fade-down');
});
}
// Mitra data
const mitraData = [
{
name: "PT. Mitra Sejahtera",
logo: "@Url.Content("~/assets/images/home/pertamina-retail.png")",
contributions: "150+ bantuan",
contributionColor: "text-ijo"
},
{
name: "CV. Media Partner",
logo: "@Url.Content("~/assets/images/home/pertamina-retail.png")",
contributions: "80+ bantuan",
contributionColor: "text-ijo"
},
{
name: "PT. Teknologi Maju",
logo: "@Url.Content("~/assets/images/home/pertamina-retail.png")",
contributions: "20+ bantuan",
contributionColor: "text-ijo"
},
{
name: "PT. Eco Solutions",
logo: "@Url.Content("~/assets/images/home/pertamina-retail.png")",
contributions: "50+ bantuan",
contributionColor: "text-ijo"
},
{
name: "PT. Green Energy",
logo: "@Url.Content("~/assets/images/home/pertamina-retail.png")",
contributions: "95+ bantuan",
contributionColor: "text-ijo"
},
{
name: "CV. Sustainable Future",
logo: "@Url.Content("~/assets/images/home/pertamina-retail.png")",
contributions: "65+ bantuan",
contributionColor: "text-ijo"
}
];
// Configuration
const isMobile = window.innerWidth < 768;
const cardsPerSlide = isMobile ? 1 : 3; // Show 1 card on mobile, 3 on desktop
const slider = document.getElementById('slider-mitra');
const dotsContainer = document.getElementById('mitra-dots');
const nextBtn = document.getElementById('next-mitra-btn');
const prevBtn = document.getElementById('prev-mitra-btn');
// Calculate how many slides we need
const totalSlides = Math.ceil(mitraData.length / cardsPerSlide);
// Generate slides with horizontal logos
for (let i = 0; i < totalSlides; i++) {
const slideDiv = document.createElement('div');
slideDiv.className = 'flex-shrink-0 w-full';
// Create a flex container for horizontal layout
const flexContainer = document.createElement('div');
// Add gap-2 for mobile to prevent overflow
flexContainer.className = `flex flex-row justify-between ${isMobile ? 'gap-2' : 'gap-6'}`;
// Get mitras for this slide
const startIndex = i * cardsPerSlide;
const slideMitras = mitraData.slice(startIndex, startIndex + cardsPerSlide);
// Create cards for this slide
slideMitras.forEach(mitra => {
const card = document.createElement('div');
card.className = 'mitra-card bg-white rounded-xl p-5 shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 flex-1';
card.innerHTML = `
<div class="text-center">
<img src="${mitra.logo}" alt="${mitra.name}" class="w-24 h-24 mx-auto object-contain mb-4 rounded-lg">
<h3 class="font-bold text-gray-800 text-sm">${mitra.name}</h3>
<div class="bg-orange-100 text-orange-800 text-xs font-medium px-2 py-0.5 rounded-full inline-block my-2">
Mitra of the Year
</div>
<p class="text-gray-600 text-xs leading-relaxed">
<span class="font-semibold ${mitra.contributionColor}">${mitra.contributions}</span>
</p>
<button class="mt-3 text-orange-600 hover:text-orange-800 text-xs font-medium flex items-center justify-center mx-auto transition-colors duration-300">
Telusuri
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 ml-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
</svg>
</button>
</div>
`;
flexContainer.appendChild(card);
});
// If we have fewer than cardsPerSlide, add empty placeholders to maintain layout
if (slideMitras.length < cardsPerSlide) {
for (let j = slideMitras.length; j < cardsPerSlide; j++) {
const placeholder = document.createElement('div');
placeholder.className = 'flex-1';
flexContainer.appendChild(placeholder);
}
}
slideDiv.appendChild(flexContainer);
slider.appendChild(slideDiv);
}
// Create navigation dots
for (let i = 0; i < totalSlides; i++) {
const dot = document.createElement('button');
dot.className = `w-2 h-2 rounded-full transition-all duration-300 ${i === 0 ? 'bg-oren w-6' : 'bg-gray-300'}`;
dot.setAttribute('data-index', i);
dot.onclick = () => goToSlide(i);
dotsContainer.appendChild(dot);
}
// Slider functionality
let currentSlide = 0;
function goToSlide(index) {
if (index < 0 || index >= totalSlides || index === currentSlide) return;
// Use GSAP for smooth animation
gsap.to(slider, {
x: `-${index * 100}%`,
duration: 0.6,
ease: "power2.out"
});
currentSlide = index;
updateDots();
updateButtons();
}
function updateDots() {
const dots = dotsContainer.querySelectorAll('button');
dots.forEach((dot, index) => {
if (index === currentSlide) {
dot.classList.add('bg-orange-600', 'w-6');
dot.classList.remove('bg-gray-300');
} else {
dot.classList.add('bg-gray-300');
dot.classList.remove('bg-orange-600', 'w-6');
}
});
}
function updateButtons() {
prevBtn.disabled = currentSlide === 0;
nextBtn.disabled = currentSlide === totalSlides - 1;
prevBtn.style.opacity = currentSlide === 0 ? '0.5' : '1';
nextBtn.style.opacity = currentSlide === totalSlides - 1 ? '0.5' : '1';
}
// Navigation
nextBtn.addEventListener('click', () => {
goToSlide(currentSlide + 1);
});
prevBtn.addEventListener('click', () => {
goToSlide(currentSlide - 1);
});
// Handle window resize to adjust for orientation changes
window.addEventListener('resize', function() {
// Recalculate isMobile
const wasMobile = isMobile;
const newIsMobile = window.innerWidth < 768;
// If mobile state changed, reload the page to rebuild the carousel
if (wasMobile !== newIsMobile) {
location.reload();
}
});
// Add touch swipe support for mobile
if (isMobile) {
let touchStartX = 0;
let touchEndX = 0;
slider.addEventListener('touchstart', function(e) {
touchStartX = e.changedTouches[0].screenX;
}, {passive: true});
slider.addEventListener('touchend', function(e) {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
}, {passive: true});
function handleSwipe() {
if (touchEndX < touchStartX - 50) {
// Swipe left - go to next slide
goToSlide(currentSlide + 1);
}
if (touchEndX > touchStartX + 50) {
// Swipe right - go to previous slide
goToSlide(currentSlide - 1);
}
}
}
// Add card entrance animation
const cards = document.querySelectorAll('.mitra-card');
gsap.fromTo(cards,
{ y: 30, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.8,
stagger: 0.1,
ease: "power2.out",
delay: 0.3
}
);
// Initialize buttons state
updateButtons();
});
</script>
</register-block>