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
Binary file added src/assets/2014 (2).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2014 (3).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2014.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2016 (2).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2016.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2017 (2).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2017 (3).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2017.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2022.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2023 (2).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2023.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2024.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2025 (2).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2025 (3).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2025 (4).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2025 (5).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2025 (6).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/2025.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 87 additions & 2 deletions src/components/AchievementCard.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,89 @@
import { Calendar, Award, TrendingUp } from "lucide-react";
import {
Calendar,
Award,
TrendingUp,
ChevronLeft,
ChevronRight,
} from "lucide-react";
import { useState, useEffect } from "react";

const AchievementCard = ({ title, description, year, isLeft, index }) => {
const ImageCarousel = ({ images, title }) => {
const [currentIndex, setCurrentIndex] = useState(0);

const nextImage = () => {
setCurrentIndex((prevIndex) =>
prevIndex === images.length - 1 ? 0 : prevIndex + 1,
);
};

const prevImage = () => {
setCurrentIndex((prevIndex) =>
prevIndex === 0 ? images.length - 1 : prevIndex - 1,
);
};

if (!images || images.length === 0) return null;

return (
<div className="mb-4 overflow-hidden rounded-lg relative group">
<div className="w-full h-48 bg-gray-100 flex items-center justify-center">
<img
src={images[currentIndex]}
alt={`${title} - Image ${currentIndex + 1}`}
className="w-full h-full object-contain transition-transform duration-500 group-hover:scale-105"
onError={(e) => {
e.target.style.display = "none";
}}
/>
</div>

{/* Navigation arrows - only show if multiple images */}
{images.length > 1 && (
<>
<button
onClick={prevImage}
className="absolute left-2 top-1/2 transform -translate-y-1/2 bg-black/50 hover:bg-black/70 text-white p-1 rounded-full transition-all duration-300 opacity-0 group-hover:opacity-100 z-10"
aria-label="Previous image"
>
<ChevronLeft className="h-4 w-4" />
</button>
<button
onClick={nextImage}
className="absolute right-2 top-1/2 transform -translate-y-1/2 bg-black/50 hover:bg-black/70 text-white p-1 rounded-full transition-all duration-300 opacity-0 group-hover:opacity-100 z-10"
aria-label="Next image"
>
<ChevronRight className="h-4 w-4" />
</button>

{/* Image indicators */}
<div className="absolute bottom-2 left-1/2 transform -translate-x-1/2 flex space-x-1 z-10">
{images.map((_, index) => (
<button
key={index}
onClick={() => setCurrentIndex(index)}
className={`w-2 h-2 rounded-full transition-all duration-300 ${
index === currentIndex
? "bg-white"
: "bg-white/50 hover:bg-white/75"
}`}
aria-label={`Go to image ${index + 1}`}
/>
))}
</div>
</>
)}
</div>
);
};

const AchievementCard = ({
title,
description,
year,
isLeft,
index,
images,
}) => {
const [isVisible, setIsVisible] = useState(false);
const [isHovered, setIsHovered] = useState(false);

Expand Down Expand Up @@ -63,6 +145,9 @@ const AchievementCard = ({ title, description, year, isLeft, index }) => {
</div>

<div className="relative p-6 pt-8">
{/* Image Carousel Section */}
<ImageCarousel images={images} title={title} />

{/* Year badge with enhanced styling */}
<div className="flex items-center justify-between mb-4">
<div className="flex items-center text-[#0B2044] text-sm font-semibold bg-[#51B8F2]/10 px-3 py-1.5 rounded-full">
Expand Down
3 changes: 3 additions & 0 deletions src/components/Timeline.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ const Timeline = () => {
year={achievement.year}
isLeft={true}
index={index}
images={achievement.images}
/>
</div>
)}
Expand Down Expand Up @@ -254,6 +255,7 @@ const Timeline = () => {
year={achievement.year}
isLeft={false}
index={index}
images={achievement.images}
/>
</div>
)}
Expand All @@ -276,6 +278,7 @@ const Timeline = () => {
year={achievement.year}
isLeft={true}
index={index}
images={achievement.images}
/>
</div>
</div>
Expand Down
43 changes: 43 additions & 0 deletions src/config/achievement.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
// Import all year-based images
import img2014 from "../assets/2014.png";
import img2014_2 from "../assets/2014 (2).png";
import img2014_3 from "../assets/2014 (3).png";
import img2016 from "../assets/2016.png";
import img2016_2 from "../assets/2016 (2).png";
import img2017 from "../assets/2017.png";
import img2017_2 from "../assets/2017 (2).png";
import img2017_3 from "../assets/2017 (3).png";
import img2022 from "../assets/2022.png";
import img2023 from "../assets/2023.png";
import img2023_2 from "../assets/2023 (2).png";
import img2024 from "../assets/2024.png";
import img2025 from "../assets/2025.png";
import img2025_2 from "../assets/2025 (2).png";
import img2025_3 from "../assets/2025 (3).png";
import img2025_4 from "../assets/2025 (4).png";
import img2025_5 from "../assets/2025 (5).png";
import img2025_6 from "../assets/2025 (6).png";

// Organize images by year
const yearImages = {
2014: [img2014, img2014_2, img2014_3],
2016: [img2016, img2016_2],
2017: [img2017, img2017_2, img2017_3],
2022: [img2022],
2023: [img2023, img2023_2],
2024: [img2024],
2025: [img2025, img2025_2, img2025_3, img2025_4],
"2025a": [img2025_5, img2025_6],
};

const achievementsData = [
{
id: 1,
Expand All @@ -7,6 +39,7 @@ const achievementsData = [
year: "2021",
category: "HPVC",
rank: "3rd Global",
images: yearImages["2021"] || null,
},
{
id: 2,
Expand All @@ -16,6 +49,7 @@ const achievementsData = [
year: "2022",
category: "HPVC",
rank: "2nd Global",
images: yearImages["2022"] || null,
},
{
id: 3,
Expand All @@ -24,6 +58,7 @@ const achievementsData = [
year: "2023",
category: "Design",
rank: "9th Global",
images: yearImages["2023"] || null,
},
{
id: 4,
Expand All @@ -33,6 +68,7 @@ const achievementsData = [
year: "2024",
category: "XRC",
rank: "1st Place",
images: yearImages["2024"] || null,
},
{
id: 5,
Expand All @@ -42,6 +78,7 @@ const achievementsData = [
year: "2025",
category: "HPVC",
rank: "3rd Overall",
images: yearImages["2025"] || null,
},
{
id: 6,
Expand All @@ -51,6 +88,7 @@ const achievementsData = [
year: "2019",
category: "HPVC",
rank: "13th Overall",
images: yearImages["2019"] || null,
},
{
id: 7,
Expand All @@ -60,6 +98,7 @@ const achievementsData = [
year: "2017",
category: "HPVC",
rank: "20th Place",
images: yearImages["2017"] || null,
},
{
id: 8,
Expand All @@ -69,6 +108,7 @@ const achievementsData = [
year: "2016",
category: "HPVC",
rank: "2nd Design",
images: yearImages["2016"] || null,
},
{
id: 9,
Expand All @@ -77,6 +117,7 @@ const achievementsData = [
year: "2015",
category: "HPVC",
rank: "Best Innovation",
images: yearImages["2015"] || null,
},
{
id: 10,
Expand All @@ -86,6 +127,7 @@ const achievementsData = [
year: "2014",
category: "HPVC",
rank: "Best Analysis",
images: yearImages["2014"] || null,
},
{
id: 11,
Expand All @@ -95,6 +137,7 @@ const achievementsData = [
year: "2025",
category: "Design",
rank: "2nd Overall",
images: yearImages["2025a"] || null,
},
];

Expand Down
Loading