Skip to content
Open
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
333 changes: 322 additions & 11 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,23 @@
"framer-motion": "^11.1.7",
"gsap": "^3.12.5",
"lil-gui": "^0.19.2",
"lucide-react": "^0.473.0",
"react": "^18.2.0",
"react-chrono": "^2.6.1",
"react-d3-cloud": "^1.0.6",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.5.1",
"react-icon-cloud": "^1.1.3",
"react-icons": "^5.2.1",
"react-lazy-load-image-component": "^1.6.3",
"react-router-dom": "^6.23.0",
"react-spring": "^9.7.3",
"react-three-fiber": "^6.0.13",
"react-use": "^17.6.0",
"simple-icons": "^5.24.0",
"stats.js": "^0.17.0",
"three": "^0.165.0",
"typewriter-effect": "^2.21.0",
"uuid": "^8.3.2"
},
"devDependencies": {
Expand Down
6 changes: 5 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import VerticalTimeline from './Components/Timeline';
import Carousel from './Components/Carousel';
import Hero from './Components/Hero';
import Footer from "./Components/Footer"
import LeaderboardComponent from './Components/LeaderboardComponent';
import AchievementsPage from './Components/Achievements';



const Homepage = () => {
return (
<div>
<Hero />
{/* Text Section between Hero and Carousel */}
<div className="text-center py-8 px-4 md:px-12 bg-opacity-10 text-white">
<h2 className="text-4xl font-semibold mb-4">Welcome to Project X</h2>
<p className="text-xl">
Expand All @@ -32,6 +34,7 @@ const Homepage = () => {
<div>
<Carousel />
</div>

</div>
);
};
Expand All @@ -52,6 +55,7 @@ function App() {
<Route path="/past-projects" element={<PastProjects />} />
<Route path="/upcoming-projects" element={<UpcomingProjects />} />
{/* <Route path="/time" element={<VerticalTimeline />} /> */}
<Route path="/LeaderboardComponent" element={<LeaderboardComponent/>} />

{/* <Route path="/" element={<OrderManagement />} /> */}
</Routes>
Expand Down
314 changes: 290 additions & 24 deletions src/Components/Achievements.jsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,297 @@
import React from 'react';
import CircularCard from './CircularCard';
import React, { useState, useEffect } from 'react';
import Typewriter from 'typewriter-effect';
import toast, { Toaster } from 'react-hot-toast';

const AchievementsPage = () => {
const [showForm, setShowForm] = useState(false); // For toggling the modal form
const [sections, setSections] = useState({}); // Dynamic sections

// Load sections from localStorage on component mount
useEffect(() => {
const savedSections = localStorage.getItem('sections');
if (savedSections) {
setSections(JSON.parse(savedSections));
}
}, []);

const handleAddEntry = (sectionName, newEntry) => {
setSections((prevSections) => {
const updatedSections = { ...prevSections };
if (!updatedSections[sectionName]) {
updatedSections[sectionName] = [];
}
updatedSections[sectionName].push(newEntry);
localStorage.setItem('sections', JSON.stringify(updatedSections));
return updatedSections;
});

setShowForm(false);
// Show success toast
toast.success('Achievement added successfully! 🎉');
};

const Achievements = () => {
return (
<div className='min-h-screen'>
<h1 className="text-center mx-auto text-5xl font-mono py-12 bg-clip-text text-transparent bg-gradient-to-r from-purple-400 via-pink-300 to-red-300">
GSoC Contributors
</h1>
<div className="grid grid-cols-6 px-3 gap-12 justify-center">
<div></div>
<CircularCard image='https://i.ibb.co/jJyjcvZ/Kshitij-Shah-photoaidcom-cropped.png' name='Kshitij Shah' organization='Sugarlabs' link="https://github.com/kshitijdshah99/Pippy_Activity" />
<CircularCard image='https://i.ibb.co/Z6fgX5F/IMG-20231110-003535-01-01-photoaidcom-cropped.png' name='Vedant Mehra' organization='CERN' link="https://hepsoftwarefoundation.org/gsoc/blogs/2024/blog_SOFIE_VedantMehra.html" />
<CircularCard image='https://i.ibb.co/Sm9FtJ2/1714656497995-photoaidcom-cropped.png' name='Mayank Palan' organization='Red Hen Lab' link="https://medium.com/@mayankpalan066/gsoc24-with-red-hen-lab-modeling-wayfinding-cfb0131b71d1" />
<CircularCard image='https://i.ibb.co/C640S72/Scanned-20240502-1627-1-page-0001-photoaidcom-cropped.png' name='Sharan Poojari' organization='NumFOCUS' link="https://github.com/aiidateam/aiida-explorer/blob/gsoc/gsoc/README.md" />
<div></div>
<div className="relative bg-transparent min-h-screen w-full flex flex-col items-center">
<Toaster position="top-center" reverseOrder={false} />

{/* Header Section */}
<div className="w-full text-center py-16">
<h1 className="text-bounce text-6xl font-mono tracking-widest text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500">
<Typewriter
options={{
strings: ['Achievements'],
autoStart: true,
loop: true,
}}
/>
</h1>
</div>
<div className="grid grid-cols-7 px-6 justify-center gap-12">
<div></div>
<div></div>
<CircularCard image='https://i.ibb.co/T4D9vMh/IMG-20240502-172654-photoaidcom-cropped.png' name='Warren Jacinto' organization='Open Astronomy' link="https://deadspheroid.github.io/my-blog/" />
<CircularCard image='https://i.ibb.co/t3vy9D9/IMG-20240502-WA0043-2-photoaidcom-cropped.png' name='Tvisha Vedant' organization='INCF' link="https://tvilight4.github.io/MyBlog/" />
<CircularCard image='https://i.ibb.co/9WSz3ss/photo-photoaidcom-cropped.png' name='Raya Chakravarthy' organization='INCF' link="https://raya679.github.io/gsoc/" />
<div></div>
<div></div>

{/* Add Button */}
<button
onClick={() => setShowForm(true)}
className="absolute top-16 right-10 bg-gradient-to-r from-blue-600 to-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-full shadow-xl transform hover:scale-105 transition-transform"
>
+ Add Achievement
</button>

{/* Achievements Sections */}
<div className="w-full px-12 py-8 space-y-12">
{Object.keys(sections).length > 0 ? (
Object.entries(sections).map(([section, entries], index) => (
<div key={index}>
<div className="flex justify-center">
<h2 className="inline-block text-5xl font-mono py-3 font-bold mb-6 text-pink-300 border-b-4 border-blue-600">
{section}
</h2>
</div>
<div className="grid grid-cols-3 gap-6">
{entries.map((entry, i) => (
<AchievementCard
key={i}
title={entry.title}
description={entry.description}
participants={entry.participants}
branch={entry.branch}
image={entry.image}
/>
))}
</div>
</div>
))
) : (
<p className="text-center text-gray-400 text-xl font-mono">
No entries yet. Add some achievements or competitions!
</p>
)}
</div>

{/* Form Modal */}
{showForm && (
<FormModal
sections={Object.keys(sections)}
onClose={() => setShowForm(false)}
onSubmit={handleAddEntry}
/>
)}
</div>
);
};

const AchievementCard = ({ title, description, participants, branch, image }) => {
const [isExpanded, setIsExpanded] = useState(false);

const toggleDescription = () => {
setIsExpanded(!isExpanded);
};

return (
<div
className="ml-[15%] shadow-lg rounded-lg overflow-hidden transform transition-transform hover:scale-105 border border-gray-200 w-80"
style={{
background: 'linear-gradient(to bottom, #0f0e17, #232946)',
color: '#eebbc3',
}}
>
{image && (
<div className="relative">
<img src={image} alt={title} className="w-full h-40 object-cover" />
</div>
)}
<div className="p-4 bg-transparent">
<h3 className="text-2xl text-center font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-500 to-purple-600 mb-1">
{title}
</h3>
<p className="text-md text-gray-350 font-semibold mb-2">
Participants: {participants}
</p>
<p className="text-md text-gray-350 font-semibold mb-2">
Branch: {branch}
</p>
<div className="text-md text-gray-350 font-semibold mb-2">
<span className="font-bold">Description:</span>
<p
className={`${
isExpanded ? 'whitespace-normal' : 'overflow-hidden text-ellipsis max-h-12'
} break-words`}
>
{description}
</p>
<div className="text-right mt-2">
<button
onClick={toggleDescription}
className="py-1 text-indigo-300 text-sm uppercase hover:underline"
>
{isExpanded ? 'Show Less' : 'Read More'} <span>&rarr;</span>
</button>
</div>
</div>
</div>
</div>
);
};

const FormModal = ({ sections, onClose, onSubmit }) => {
const [isNewSection, setIsNewSection] = useState(true);
const [sectionName, setSectionName] = useState('');
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const [participants, setParticipants] = useState('');
const [branch, setBranch] = useState('');
const [image, setImage] = useState('');

const handleSubmit = (e) => {
e.preventDefault();

// Validate the description length (less than 30 words)
const descriptionWordCount = description.trim().split(/\s+/).length;
if (descriptionWordCount > 30) {
alert('Description must be less than 30 words.');
return;
}

const newEntry = { title, description, participants, branch, image };
if (isNewSection) {
onSubmit(sectionName, newEntry); // Add to new section
} else {
onSubmit(sectionName, newEntry); // Add to selected section
}
};

return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="relative bg-white rounded-lg shadow-lg p-6 w-1/3">
{/* Close button at the top-right */}
<button
onClick={onClose}
className="absolute top-2 right-2 text-gray-500 hover:text-gray-700 text-lg font-bold"
>
&times;
</button>
<h2 className="text-xl font-bold text-center mb-4">
{isNewSection ? 'Add New Section' : 'Add Entry to Section'}
</h2>
<form onSubmit={handleSubmit} className="space-y-4">
{isNewSection ? (
<div>
<label className="block font-semibold">Section Name</label>
<input
type="text"
value={sectionName}
onChange={(e) => setSectionName(e.target.value)}
className="w-full p-2 border rounded"
required
/>
</div>
) : (
<div>
<label className="block font-semibold">Select Section</label>
<select
value={sectionName}
onChange={(e) => setSectionName(e.target.value)}
className="w-full p-2 border rounded"
required
>
<option value="">-- Select a Section --</option>
{sections.map((section, index) => (
<option key={index} value={section}>
{section}
</option>
))}
</select>
</div>
)}
<div>
<label className="block font-semibold">Title</label>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
className="w-full p-2 border rounded"
required
/>
</div>
<div>
<label className="block font-semibold">Description</label>
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
className="w-full p-2 border rounded"
required
></textarea>
</div>
<div>
<label className="block font-semibold">Participants</label>
<input
type="text"
value={participants}
onChange={(e) => setParticipants(e.target.value)}
className="w-full p-2 border rounded"
required
/>
</div>
<div>
<label className="block font-semibold">Branch</label>
<input
type="text"
value={branch}
onChange={(e) => setBranch(e.target.value)}
className="w-full p-2 border rounded"
required
/>
</div>
<div>
<label className="block font-semibold">Image URL</label>
<input
type="text"
value={image}
onChange={(e) => setImage(e.target.value)}
className="w-full p-2 border rounded"
placeholder="Enter image URL"
/>
</div>
<div className="flex justify-between">
<button
type="button"
onClick={() => {
setIsNewSection(!isNewSection);
setSectionName('');
}}
className="bg-gray-300 hover:bg-gray-400 text-black font-bold py-2 px-4 rounded"
>
{isNewSection ? 'Add to Existing Section' : 'Create New Section'}
</button>
<button
type="submit"
className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded"
>
Add Entry
</button>
</div>
</form>
</div>
</div>
);
}
};

export default Achievements;
export default AchievementsPage;
Loading