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
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"lucide-react": "^0.525.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
Expand Down
Empty file removed src/config/achievement.js
Empty file.
49 changes: 49 additions & 0 deletions src/config/achievement.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const achievementsData = [
{
id: 1,
title: "Name",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
image:
"https://images.unsplash.com/photo-1593376853899-fbb47a057fa0?w=600&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cm9ib3RzfGVufDB8fDB8fHww",
date: "December 2023",
},
{
id: 2,
title: "Name",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
image:
"https://images.unsplash.com/photo-1593376853899-fbb47a057fa0?w=600&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cm9ib3RzfGVufDB8fDB8fHww",
date: "December 2023",
},
{
id: 3,
title: "Name",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
image:
"https://images.unsplash.com/photo-1593376853899-fbb47a057fa0?w=600&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cm9ib3RzfGVufDB8fDB8fHww",
date: "December 2023",
},
{
id: 4,
title: "Name",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
image:
"https://images.unsplash.com/photo-1593376853899-fbb47a057fa0?w=600&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cm9ib3RzfGVufDB8fDB8fHww",
date: "December 2023",
},
{
id: 5,
title: "Name",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
image:
"https://images.unsplash.com/photo-1593376853899-fbb47a057fa0?w=600&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cm9ib3RzfGVufDB8fDB8fHww",
date: "December 2023",
},
];

export default achievementsData;
54 changes: 54 additions & 0 deletions src/config/achievementCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Calendar } from "lucide-react";

const AchievementCard = ({
title,
description,
image,
date,
isLeft,
index,
}) => {
return (
<div
className={`flex items-center w-full mb-16 ${isLeft ? "justify-start" : "justify-end"}`}
style={{ animationDelay: `${index * 200}ms` }}
>
<div
className={`
w-full max-w-md bg-gradient-card rounded-2xl shadow-card hover:shadow-card-hover
transition-all duration-500 hover:scale-105 group cursor-pointer
${isLeft ? "animate-slide-in-left" : "animate-slide-in-right"}
`}
>
{/* Image */}
<div className="relative overflow-hidden rounded-t-2xl">
<img
src={image}
alt={title}
className="w-full h-48 object-cover transition-transform duration-500 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-primary/10 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
</div>

{/* Content */}
<div className="p-6">
<div className="flex items-center text-muted text-sm mb-3">
<Calendar className="h-4 w-4 mr-2" />
<span className="font-medium">{date}</span>
</div>

<h3 className="text-xl font-bold text-foreground mb-3 group-hover:text-primary transition-colors duration-300">
{title}
</h3>

<p className="text-muted ">{description}</p>

{/* Decorative element */}
<div className="mt-4 h-1 w-16 bg-gradient-primary rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
</div>
</div>
</div>
);
};

export default AchievementCard;
130 changes: 130 additions & 0 deletions src/config/timeline.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { useEffect, useRef, useState } from "react";
import AchievementCard from "./achievementCard";
import achievementsData from "./achievement";

const Timeline = () => {
const timelineRef = useRef(null);
const [visibleDots, setVisibleDots] = useState(new Set());

useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const index = parseInt(
entry.target.getAttribute("data-index") || "0",
);
setVisibleDots((prev) => new Set([...prev, index]));
}
});
},
{ threshold: 0.5 },
);

const cards = document.querySelectorAll("[data-index]");
cards.forEach((card) => observer.observe(card));

return () => observer.disconnect();
}, []);

return (
<section
id="achievements"
className="bg-gradient-to-br from-background to-muted/30"
>
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Header */}
<div style={{ marginBottom: "7rem" }}>
<h2 className="text-3xl text-center font-bold text-blue-900 mb-4">
Our Achievements
</h2>
<p className="text-gray-700 text-center mb-6 max-w-3xl">
ASME NIT Rourkela excels in fostering innovation and leadership
through workshops, competitions, and expert lectures. Recognized for
achievements in events like the Student Design Challenge and HPVC,
the chapter addresses real-world problems with engineering
creativity. Their STEM outreach initiatives further enhance their
impact, solidifying their reputation for excellence in mechanical
engineering.
</p>
</div>
{/* Timeline */}
<div className="relative" ref={timelineRef}>
<div className="grid grid-cols-9 gap-2">
{achievementsData.map((achievement, index) => (
<div key={achievement.id} className="contents">
{/* Left card */}
<div
className={`col-span-4 ${index % 2 === 0 ? "flex justify-end" : ""} hidden md:flex`}
>
{index % 2 === 0 && (
<div className="w-full max-w-md">
<AchievementCard
title={achievement.title}
description={achievement.description}
image={achievement.image}
date={achievement.date}
isLeft={true}
index={index}
/>
</div>
)}
</div>
{/* Timeline line and dot */}
<div className="col-span-1 flex flex-col items-center relative">
{/* Vertical line */}
<div className="w-1 bg-gray-300 h-full absolute top-0 left-1/2 -translate-x-1/2 z-0"></div>

{/* Timeline dot */}
<div className="z-10">
<div
className={`w-4 h-4 rounded-full border-background bg-yellow-500 border-2 border-white transition-all duration-500
${
visibleDots.has(index)
? "bg-timeline-dot-active shadow-glow animate-glow-pulse"
: "bg-timeline-dot"
}
`}
></div>
</div>
</div>
{/* Right card */}
<div
className={`col-span-4 ${index % 2 !== 0 ? "flex justify-start" : ""} hidden md:flex`}
>
{index % 2 !== 0 && (
<div className="w-full max-w-md">
<AchievementCard
title={achievement.title}
description={achievement.description}
image={achievement.image}
date={achievement.date}
isLeft={false}
index={index}
/>
</div>
)}
</div>
{/* Mobile view: single column, card below dot/line */}
<div className="col-span-9 flex justify-center md:hidden">
<div className="w-full max-w-md">
<AchievementCard
title={achievement.title}
description={achievement.description}
image={achievement.image}
date={achievement.date}
isLeft={true}
index={index}
/>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</section>
);
};

export default Timeline;
4 changes: 4 additions & 0 deletions src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import Footer from "./components/playground/Footer.jsx";
import Playground from "./Playground.jsx";
import Test from "./components/playground/Test.jsx";
import Home from "./pages/playground/landing-page/Home.jsx";
import Achievements from "./pages/playground/Achievements.jsx";
import AchievementPage from "./pages/playground/AchievementPage.jsx";
import Events from "./pages/playground/landing-page/Events.jsx";

createRoot(document.getElementById("root")).render(
Expand All @@ -18,6 +20,8 @@ createRoot(document.getElementById("root")).render(
<Route index element={<Home />} />
<Route path="test" element={<Test />} />
<Route path="events" element={<Events />} />
<Route path="achievement" element={<Achievements />} />
<Route path="achievementpage" element={<AchievementPage />} />
</Route>
</Routes>
</BrowserRouter>
Expand Down
13 changes: 13 additions & 0 deletions src/pages/playground/AchievementPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Timeline from "../../config/timeline";

const AchievementPage = () => {
return (
<div className="min-h-screen bg-background flex flex-col items-center py-12">
<div className="w-full max-w-4xl">
<Timeline />
</div>
</div>
);
};

export default AchievementPage;
57 changes: 57 additions & 0 deletions src/pages/playground/Achievements.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { useNavigate } from "react-router";
import achievementsData from "../../config/achievement";

export default function Achievements() {
const navigate = useNavigate();

return (
<div className="px-4 md:px-12 py-8 max-w-screen-xl mx-auto">
<div style={{ marginBottom: "12rem" }}>
<h2 className="text-3xl font-bold text-blue-900 mb-4">
Our Achievements
</h2>
<p className="text-gray-700 mb-6 max-w-3xl">
ASME NIT Rourkela excels in fostering innovation and leadership
through workshops, competitions, and expert lectures. Recognized for
achievements in events like the Student Design Challenge and HPVC, the
chapter addresses real-world problems with engineering creativity.
Their STEM outreach initiatives further enhance their impact,
solidifying their reputation for excellence in mechanical engineering.
</p>
<button
className="bg-white text-blue-800 border border-blue-800 px-4 py-2 rounded hover:bg-blue-50 mb-12"
onClick={() => navigate("/achievementpage")}
>
View All Achievements &gt;
</button>
</div>

<div className="relative">
<div className="hidden md:block absolute top-1/2 left-0 w-full h-1 bg-black -translate-y-1/2 z-0"></div>
<div className="md:hidden absolute left-2 top-0 h-full w-1 bg-black z-0"></div>

<div className="flex flex-col md:flex-row items-start md:items-center justify-between relative z-10">
{achievementsData.map((item, index) => (
<div
key={index}
className={`w-full md:w-1/4 px-4 mb-16 md:mb-0 flex md:flex-col items-start md:items-center relative`}
>
<div className="absolute md:static left-0 md:left-auto top-2 md:top-auto md:mb-4 transform -translate-y-1/2 md:translate-y-1/2 w-4.5 h-4.5 bg-black border-2 border-white rounded-full z-20"></div>

<div
className={`bg-white p-4 rounded-md w-full max-w-xs md:mt-0 md:absolute ${
index % 2 === 0
? "md:top-1/2 md:translate-y-6 self-start"
: "md:bottom-1/2 md:-translate-y-6 self-end"
}`}
>
<h3 className="font-bold text-lg text-black">{item.title}</h3>
<p className="text-sm text-gray-600 mt-2">{item.description}</p>
</div>
</div>
))}
</div>
</div>
</div>
);
}