2025-10-14 19:22:07 +05:30
|
|
|
// components/CaseStudySlider.tsx
|
|
|
|
|
import { motion } from "framer-motion";
|
|
|
|
|
import {
|
|
|
|
|
Activity,
|
|
|
|
|
ArrowUpRight,
|
|
|
|
|
Building2,
|
|
|
|
|
ChevronLeft, ChevronRight,
|
|
|
|
|
FlaskConical,
|
|
|
|
|
Globe,
|
|
|
|
|
Heart,
|
|
|
|
|
Package,
|
|
|
|
|
PartyPopper,
|
|
|
|
|
ShoppingCart,
|
|
|
|
|
Star,
|
|
|
|
|
Tractor,
|
|
|
|
|
TrendingUp,
|
|
|
|
|
Trophy,
|
|
|
|
|
Tv,
|
|
|
|
|
Users,
|
|
|
|
|
Utensils
|
|
|
|
|
} from "lucide-react";
|
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
|
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
|
import ambleCase from "../src/images/amble-case.webp";
|
|
|
|
|
import amozCase from "../src/images/amozCase.webp";
|
|
|
|
|
import dkCase from "../src/images/dkCase.webp";
|
|
|
|
|
import farmCase from "../src/images/farmCase.webp";
|
|
|
|
|
import gtCase from "../src/images/gt-case.webp";
|
|
|
|
|
import leanCase from "../src/images/leanCase.webp";
|
|
|
|
|
import niftyCase from "../src/images/niftyCase.webp";
|
|
|
|
|
import prospertyCase from "../src/images/prospertyCase.webp";
|
|
|
|
|
import ranoutofCase from "../src/images/ranoutof-case.webp";
|
|
|
|
|
import RrCase from "../src/images/resturant-reward-case.webp";
|
2026-02-17 12:08:19 +05:30
|
|
|
// import seezunCase from "../src/images/seezun-case.webp";
|
2025-10-14 19:22:07 +05:30
|
|
|
import simplitendCase from "../src/images/simplitendCase.webp";
|
|
|
|
|
import tcCase from "../src/images/tc-case.webp";
|
|
|
|
|
import vib360Case from "../src/images/vib360Case.webp";
|
|
|
|
|
import wokaCase from "../src/images/woka-case.webp";
|
|
|
|
|
import { ImageWithFallback } from "./figma/ImageWithFallback";
|
|
|
|
|
import { Badge } from "./ui/badge";
|
|
|
|
|
import { Button } from "./ui/button";
|
|
|
|
|
import { Card, CardContent } from "./ui/card";
|
2026-03-30 19:33:06 +05:30
|
|
|
import { link } from "fs";
|
2025-10-14 19:22:07 +05:30
|
|
|
|
|
|
|
|
// Internal data (no need to pass props)
|
|
|
|
|
const defaultCaseStudies = [
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
title: "RanOutOf",
|
|
|
|
|
image: ranoutofCase,
|
|
|
|
|
category: "Lifestyle",
|
|
|
|
|
industry: "Consumer",
|
|
|
|
|
featured: true,
|
|
|
|
|
link: "/projects/ranoutof",
|
|
|
|
|
icon: Package
|
|
|
|
|
},
|
2026-02-17 12:08:19 +05:30
|
|
|
// {
|
|
|
|
|
// id: 2,
|
|
|
|
|
// title: "Seezun",
|
|
|
|
|
// image: seezunCase,
|
|
|
|
|
// category: "E-commerce",
|
|
|
|
|
// industry: "Retail",
|
|
|
|
|
// featured: true,
|
|
|
|
|
// link: "/projects/seezun",
|
|
|
|
|
// icon: ShoppingCart
|
|
|
|
|
// },
|
2025-10-14 19:22:07 +05:30
|
|
|
{
|
|
|
|
|
id: 3,
|
|
|
|
|
title: "Woka",
|
|
|
|
|
image: wokaCase,
|
|
|
|
|
category: "Health & Fitness",
|
|
|
|
|
industry: "Healthcare",
|
|
|
|
|
featured: true,
|
|
|
|
|
link: "/projects/woka",
|
|
|
|
|
icon: Tv
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 6,
|
|
|
|
|
title: "Traders Circuit",
|
|
|
|
|
image: tcCase,
|
|
|
|
|
category: "FinTech",
|
|
|
|
|
industry: "Finance",
|
|
|
|
|
featured: true,
|
|
|
|
|
link: "/projects/traderscircuit",
|
|
|
|
|
icon: TrendingUp
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 7,
|
|
|
|
|
title: "Good Times",
|
|
|
|
|
image: gtCase,
|
|
|
|
|
category: "Events",
|
|
|
|
|
industry: "Entertainment",
|
|
|
|
|
featured: true,
|
|
|
|
|
link: "/projects/goodtimes",
|
|
|
|
|
icon: PartyPopper
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 8,
|
|
|
|
|
title: "Resturant Reward App",
|
|
|
|
|
image: RrCase,
|
|
|
|
|
category: "Loyalty & Rewards",
|
|
|
|
|
industry: "Hospitality",
|
|
|
|
|
featured: false,
|
2026-03-30 19:33:06 +05:30
|
|
|
// link: "/comming-soon",
|
|
|
|
|
link: "", icon: Utensils
|
2025-10-14 19:22:07 +05:30
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 9,
|
|
|
|
|
title: "Amble",
|
|
|
|
|
image: ambleCase,
|
|
|
|
|
category: "Social",
|
|
|
|
|
industry: "Heritage",
|
|
|
|
|
featured: false,
|
|
|
|
|
link: "/projects/amble",
|
|
|
|
|
icon: Users
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 10,
|
|
|
|
|
title: "Amoz",
|
|
|
|
|
image: amozCase,
|
|
|
|
|
category: "Lifestyle",
|
|
|
|
|
industry: "Consumer",
|
|
|
|
|
featured: false,
|
|
|
|
|
link: "/projects/amoz",
|
|
|
|
|
icon: Heart
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 11,
|
|
|
|
|
title: "Dorf Ketal",
|
|
|
|
|
image: dkCase,
|
|
|
|
|
category: "Lifestyle",
|
|
|
|
|
industry: "Chemicals",
|
|
|
|
|
featured: false,
|
2026-03-30 19:33:06 +05:30
|
|
|
// link: "/comming-soon",
|
|
|
|
|
link: "",
|
2025-10-14 19:22:07 +05:30
|
|
|
icon: FlaskConical
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 12,
|
|
|
|
|
title: "VIB360",
|
|
|
|
|
image: vib360Case,
|
|
|
|
|
category: "Lifestyle",
|
|
|
|
|
industry: "Consumer",
|
|
|
|
|
featured: false,
|
|
|
|
|
link: "/projects/vib360",
|
|
|
|
|
icon: Activity
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 13,
|
|
|
|
|
title: "Nifty 11",
|
|
|
|
|
image: niftyCase,
|
|
|
|
|
category: "Lifestyle",
|
|
|
|
|
industry: "Consumer",
|
|
|
|
|
featured: false,
|
2026-03-30 19:33:06 +05:30
|
|
|
// link: "/comming-soon",
|
|
|
|
|
link: "", icon: Trophy
|
2025-10-14 19:22:07 +05:30
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 14,
|
|
|
|
|
title: "Prosperty",
|
|
|
|
|
image: prospertyCase,
|
|
|
|
|
category: "Lifestyle",
|
|
|
|
|
industry: "Real Estate",
|
|
|
|
|
featured: false,
|
|
|
|
|
link: "/projects/prosperty",
|
|
|
|
|
icon: Building2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 15,
|
|
|
|
|
title: "Simpletend",
|
|
|
|
|
image: simplitendCase,
|
|
|
|
|
category: "Health & Fitness",
|
|
|
|
|
industry: "Healthcare",
|
|
|
|
|
featured: false,
|
|
|
|
|
link: "/projects/simpletend",
|
|
|
|
|
icon: Activity
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 16,
|
|
|
|
|
title: "Farm Feeder",
|
|
|
|
|
image: farmCase,
|
|
|
|
|
category: "AgriTech",
|
|
|
|
|
industry: "Agriculture",
|
|
|
|
|
featured: false,
|
2026-03-30 19:33:06 +05:30
|
|
|
// link: "/comming-soon",
|
|
|
|
|
link: "", icon: Tractor
|
2025-10-14 19:22:07 +05:30
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 17,
|
|
|
|
|
title: "Lean In World",
|
|
|
|
|
image: leanCase,
|
|
|
|
|
category: "AgriTech",
|
|
|
|
|
industry: "Agriculture",
|
|
|
|
|
featured: false,
|
2026-03-30 19:33:06 +05:30
|
|
|
// link: "/comming-soon",
|
|
|
|
|
link: "", icon: Globe
|
2025-10-14 19:22:07 +05:30
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
interface CaseStudySliderProps {
|
|
|
|
|
autoPlay?: boolean;
|
|
|
|
|
autoPlayInterval?: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const CaseStudySlider = ({
|
|
|
|
|
autoPlay = false,
|
|
|
|
|
autoPlayInterval = 4000,
|
|
|
|
|
}: CaseStudySliderProps) => {
|
|
|
|
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
|
|
|
const [isAutoPlaying, setIsAutoPlaying] = useState(autoPlay);
|
|
|
|
|
const [visibleSlides, setVisibleSlides] = useState(3);
|
|
|
|
|
const sliderRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
const navigate = useNavigate();
|
|
|
|
|
|
|
|
|
|
const caseStudies = defaultCaseStudies;
|
|
|
|
|
|
|
|
|
|
const nextSlide = () => {
|
|
|
|
|
setCurrentIndex((prev) => {
|
|
|
|
|
const nextIndex = prev + 1;
|
|
|
|
|
return nextIndex > caseStudies.length - visibleSlides ? 0 : nextIndex;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const prevSlide = () => {
|
|
|
|
|
setCurrentIndex((prev) => {
|
|
|
|
|
const prevIndex = prev - 1;
|
|
|
|
|
return prevIndex < 0 ? caseStudies.length - visibleSlides : prevIndex;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const goToSlide = (index: number) => {
|
|
|
|
|
setCurrentIndex(Math.min(index, caseStudies.length - visibleSlides));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!isAutoPlaying || !autoPlay) return;
|
|
|
|
|
const interval = setInterval(nextSlide, autoPlayInterval);
|
|
|
|
|
return () => clearInterval(interval);
|
|
|
|
|
}, [isAutoPlaying, autoPlay, autoPlayInterval, visibleSlides]);
|
|
|
|
|
|
|
|
|
|
// Calculate visible slides on resize
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const updateVisibleSlides = () => {
|
|
|
|
|
if (!containerRef.current) return;
|
|
|
|
|
const width = containerRef.current.offsetWidth;
|
|
|
|
|
if (width < 640) setVisibleSlides(1);
|
|
|
|
|
else if (width < 1024) setVisibleSlides(2);
|
|
|
|
|
else setVisibleSlides(3);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateVisibleSlides();
|
|
|
|
|
window.addEventListener('resize', updateVisibleSlides);
|
|
|
|
|
return () => window.removeEventListener('resize', updateVisibleSlides);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const maxIndex = Math.max(0, caseStudies.length - visibleSlides);
|
|
|
|
|
|
|
|
|
|
// Calculate the actual translation percentage
|
|
|
|
|
const getTranslationPercentage = () => {
|
|
|
|
|
if (visibleSlides >= caseStudies.length) return 0;
|
|
|
|
|
return (currentIndex * (100 / visibleSlides));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
2026-03-30 19:33:06 +05:30
|
|
|
<section
|
2025-10-14 19:22:07 +05:30
|
|
|
className="py-20 pt-10"
|
|
|
|
|
onMouseEnter={() => setIsAutoPlaying(false)}
|
|
|
|
|
onMouseLeave={() => setIsAutoPlaying(autoPlay)}
|
|
|
|
|
ref={containerRef}
|
|
|
|
|
>
|
2026-02-17 12:08:19 +05:30
|
|
|
<div className="container px-6 mx-auto lg:px-8">
|
2025-10-14 19:22:07 +05:30
|
|
|
{/* Header */}
|
|
|
|
|
<div className="flex items-center justify-end mb-8">
|
|
|
|
|
{caseStudies.length > visibleSlides && (
|
|
|
|
|
<div className="flex items-center gap-2">
|
2026-03-30 19:33:06 +05:30
|
|
|
<Button
|
|
|
|
|
variant="outline"
|
|
|
|
|
size="icon"
|
|
|
|
|
onClick={prevSlide}
|
2025-10-14 19:22:07 +05:30
|
|
|
disabled={currentIndex === 0}
|
2026-02-17 12:08:19 +05:30
|
|
|
className="w-10 h-10 rounded-full border-white/20 hover:border-accent/50 disabled:opacity-50"
|
2025-10-14 19:22:07 +05:30
|
|
|
>
|
|
|
|
|
<ChevronLeft className="w-5 h-5" />
|
|
|
|
|
</Button>
|
2026-03-30 19:33:06 +05:30
|
|
|
<Button
|
|
|
|
|
variant="outline"
|
|
|
|
|
size="icon"
|
|
|
|
|
onClick={nextSlide}
|
2025-10-14 19:22:07 +05:30
|
|
|
disabled={currentIndex >= maxIndex}
|
2026-02-17 12:08:19 +05:30
|
|
|
className="w-10 h-10 rounded-full border-white/20 hover:border-accent/50 disabled:opacity-50"
|
2025-10-14 19:22:07 +05:30
|
|
|
>
|
|
|
|
|
<ChevronRight className="w-5 h-5" />
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Slider Container */}
|
|
|
|
|
<div className="relative overflow-hidden" ref={sliderRef}>
|
|
|
|
|
<motion.div
|
|
|
|
|
className="flex gap-6"
|
2026-03-30 19:33:06 +05:30
|
|
|
animate={{
|
|
|
|
|
x: `-${getTranslationPercentage()}%`
|
2025-10-14 19:22:07 +05:30
|
|
|
}}
|
2026-03-30 19:33:06 +05:30
|
|
|
transition={{
|
|
|
|
|
type: "spring",
|
|
|
|
|
stiffness: 400,
|
2025-10-14 19:22:07 +05:30
|
|
|
damping: 40,
|
|
|
|
|
duration: 0.6
|
|
|
|
|
}}
|
|
|
|
|
style={{ willChange: "transform" }}
|
|
|
|
|
>
|
|
|
|
|
{caseStudies.map((study, index) => {
|
|
|
|
|
const IconComponent = study.icon;
|
|
|
|
|
return (
|
|
|
|
|
<motion.div
|
|
|
|
|
key={study.id}
|
|
|
|
|
className="flex-shrink-0"
|
2026-03-30 19:33:06 +05:30
|
|
|
style={{
|
|
|
|
|
width: `calc(${100 / visibleSlides}% - 1.5rem)`
|
2025-10-14 19:22:07 +05:30
|
|
|
}}
|
|
|
|
|
initial={{ opacity: 0, scale: 0.9 }}
|
|
|
|
|
animate={{ opacity: 1, scale: 1 }}
|
2026-03-30 19:33:06 +05:30
|
|
|
transition={{
|
|
|
|
|
duration: 0.5,
|
2025-10-14 19:22:07 +05:30
|
|
|
delay: index * 0.1,
|
2026-03-30 19:33:06 +05:30
|
|
|
ease: "easeOut"
|
2025-10-14 19:22:07 +05:30
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Card
|
|
|
|
|
className="bg-card/50 backdrop-blur-md border-white/10 hover:border-accent/30 transition-all duration-500 shadow-lg hover:shadow-2xl hover:shadow-accent/10 rounded-2xl overflow-hidden h-[full] cursor-pointer"
|
|
|
|
|
onClick={() => navigate(study.link)}
|
|
|
|
|
>
|
2026-02-17 12:08:19 +05:30
|
|
|
<CardContent className="h-full p-0 CardContentOverride">
|
2025-10-14 19:22:07 +05:30
|
|
|
{/* Image */}
|
|
|
|
|
<div className="relative overflow-hidden">
|
2026-03-30 19:33:06 +05:30
|
|
|
<ImageWithFallback
|
|
|
|
|
src={study.image}
|
|
|
|
|
alt={study.title}
|
|
|
|
|
className="object-cover w-full h-full transition-transform duration-500 group-hover:scale-110"
|
2025-10-14 19:22:07 +05:30
|
|
|
/>
|
|
|
|
|
<div className="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent" />
|
2026-03-30 19:33:06 +05:30
|
|
|
|
2025-10-14 19:22:07 +05:30
|
|
|
{/* Category Badge */}
|
|
|
|
|
<div className="absolute top-2 left-4">
|
2026-02-17 12:08:19 +05:30
|
|
|
<Badge className="text-xs text-white border-0 bg-accent/90">
|
2025-10-14 19:22:07 +05:30
|
|
|
{study.category}
|
|
|
|
|
</Badge>
|
|
|
|
|
</div>
|
2026-03-30 19:33:06 +05:30
|
|
|
|
2025-10-14 19:22:07 +05:30
|
|
|
{/* Featured Badge */}
|
|
|
|
|
{study.featured && (
|
|
|
|
|
<div className="absolute top-2 right-4">
|
2026-02-17 12:08:19 +05:30
|
|
|
<div className="flex items-center gap-1 px-2 py-1 text-xs font-medium text-white rounded-full bg-amber-500/90">
|
2025-10-14 19:22:07 +05:30
|
|
|
<Star className="w-3 h-3 fill-current" />
|
|
|
|
|
Featured
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2026-03-30 19:33:06 +05:30
|
|
|
|
2025-10-14 19:22:07 +05:30
|
|
|
{/* Icon */}
|
|
|
|
|
<div className="absolute bottom-4 left-4">
|
2026-02-17 12:08:19 +05:30
|
|
|
<div className="flex items-center justify-center w-10 h-10 rounded-full bg-white/20 backdrop-blur-md">
|
2025-10-14 19:22:07 +05:30
|
|
|
<IconComponent className="w-5 h-5 text-white" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
</motion.div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</motion.div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Dots Indicator */}
|
|
|
|
|
{caseStudies.length > visibleSlides && (
|
2026-02-17 12:08:19 +05:30
|
|
|
<div className="flex items-center justify-center gap-2 mt-8">
|
2025-10-14 19:22:07 +05:30
|
|
|
{Array.from({ length: maxIndex + 1 }).map((_, index) => (
|
|
|
|
|
<button
|
|
|
|
|
key={index}
|
|
|
|
|
onClick={() => goToSlide(index)}
|
2026-03-30 19:33:06 +05:30
|
|
|
className={`w-2 h-2 rounded-full transition-all duration-300 ${index === currentIndex
|
|
|
|
|
? "bg-accent w-6"
|
2025-10-14 19:22:07 +05:30
|
|
|
: "bg-white/30 hover:bg-white/50"
|
2026-03-30 19:33:06 +05:30
|
|
|
}`}
|
2025-10-14 19:22:07 +05:30
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
);
|
|
|
|
|
};
|