File size: 27,378 Bytes
4a7a480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cc91ce3
4a7a480
 
 
cc91ce3
4a7a480
 
 
 
 
 
 
cc91ce3
4a7a480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cc91ce3
4a7a480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
797ae07
4a7a480
797ae07
 
 
 
 
 
 
4a7a480
797ae07
4a7a480
797ae07
 
 
4a7a480
 
 
797ae07
 
 
 
cc41e66
 
 
 
 
 
797ae07
cc41e66
 
 
797ae07
 
 
 
 
cc91ce3
797ae07
 
 
 
 
 
 
 
 
 
4a7a480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cc91ce3
 
 
 
 
 
4a7a480
 
cc91ce3
 
 
4a7a480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cc91ce3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d317c8
 
 
 
 
cc91ce3
 
 
 
 
 
 
 
 
 
 
 
 
 
4a7a480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
befb26b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
console.log("Script.js started executing at:", new Date().toISOString());

// Initialize Particles.js
particlesJS('particles-js', {
  particles: {
    number: { value: 80, density: { enable: true, value_area: 800 } },
    color: { value: ['#1E90FF'] },
    shape: { type: 'circle' },
    opacity: { value: 0.5, random: true },
    size: { value: 3, random: true },
    line_linked: { enable: true, distance: 150, color: '#1E90FF', opacity: 0.4, width: 1 },
    move: { enable: true, speed: 2, direction: 'none', random: true, straight: false, out_mode: 'out', bounce: false }
  },
  interactivity: {
    detect_on: 'canvas',
    events: { onhover: { enable: true, mode: 'repulse' }, onclick: { enable: true, mode: 'push' }, resize: true },
    modes: { repulse: { distance: 100, duration: 0.4 }, push: { particles_nb: 4 } }
  },
  retina_detect: true
});

// Glowing Cursor Trail
const canvas = document.getElementById('cursor-trail');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const trails = [];
window.addEventListener('mousemove', (e) => {
  trails.push({ x: e.clientX, y: e.clientY, life: 1 });
});
function animateTrail() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  trails.forEach((trail, index) => {
    ctx.beginPath();
    ctx.arc(trail.x, trail.y, 5 * trail.life, 0, Math.PI * 2);
    ctx.fillStyle = `rgba(30, 144, 255, ${trail.life})`;
    ctx.fill();
    trail.life -= 0.02;
    if (trail.life <= 0) trails.splice(index, 1);
  });
  requestAnimationFrame(animateTrail);
}
animateTrail();
window.addEventListener('resize', () => {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
});

// GSAP Animations
gsap.registerPlugin(ScrollTrigger);

// Animate the static text and buttons in hero section
gsap.fromTo('.animate-slide-in', 
  { y: 100, opacity: 0 }, 
  { y: 0, opacity: 1, duration: 1.2, ease: 'power3.out', onComplete: () => {
    document.querySelector('.animate-slide-in').style.opacity = '1';
  }}
);

// Animate the image in the hero section
gsap.fromTo('.animate-fade-in',
  { opacity: 0 },
  { opacity: 1, duration: 1.5, ease: 'power3.out', onComplete: () => {
    document.querySelector('.animate-fade-in').style.opacity = '1';
  }}
);

// Animate stat cards on scroll
gsap.from('.stat-card', {
  scrollTrigger: { trigger: '#about', start: 'top 80%' },
  y: 50,
  opacity: 0,
  duration: 0.8,
  stagger: 0.2,
  ease: 'power3.out'
});

// Navigation Bar
const menuToggle = document.getElementById('menu-toggle');
const mobileMenu = document.getElementById('mobile-menu');
menuToggle.addEventListener('click', () => {
  mobileMenu.classList.toggle('hidden');
  menuToggle.querySelector('i').classList.toggle('fa-bars');
  menuToggle.querySelector('i').classList.toggle('fa-times');
});

// Smooth Scrolling
document.querySelectorAll('.nav-link').forEach(link => {
  link.addEventListener('click', (e) => {
    e.preventDefault();
    mobileMenu.classList.add('hidden');
    menuToggle.querySelector('i').classList.add('fa-bars');
    menuToggle.querySelector('i').classList.remove('fa-times');
    document.querySelector(link.getAttribute('href')).scrollIntoView({ behavior: 'smooth' });
  });
});

// Theme Toggle (Disabled since theme switching isn't implemented)
const themeToggle = document.getElementById('theme-toggle');
themeToggle.addEventListener('click', () => {
  // Theme switching not implemented
});

// Back to Top Button
const backToTop = document.getElementById('back-to-top');
window.addEventListener('scroll', () => {
  backToTop.classList.toggle('hidden', window.scrollY < 500);
});
backToTop.addEventListener('click', () => {
  window.scrollTo({ top: 0, behavior: 'smooth' });
});

// Ripple Effect for Buttons
document.querySelectorAll('.ripple').forEach(btn => {
  btn.addEventListener('click', (e) => {
    const rect = btn.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    const ripple = document.createElement('span');
    ripple.style.left = `${x}px`;
    ripple.style.top = `${y}px`;
    ripple.classList.add('ripple-effect');
    btn.appendChild(ripple);
    setTimeout(() => ripple.remove(), 600);
  });
});

// Fetch Data Helper
const fetchData = async (url, elementId, renderCallback) => {
  try {
    console.log(`Fetching data from ${url}`);
    const response = await fetch(url);
    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
    const data = await response.json();
    console.log(`Fetched data from ${url}:`, data);
    const container = document.getElementById(elementId);
    if (!container) throw new Error(`Container with ID ${elementId} not found`);
    renderCallback(data, container);
  } catch (error) {
    console.error(`Error fetching ${url}:`, error);
    document.getElementById(elementId).innerHTML = '<p class="text-red-500">Error loading data. Please try again later.</p>';
  }
};

// Render Skills with Circular Progress
fetchData('/api/skills', 'skills-grid', (data, container) => {
  console.log('Rendering skills data:', data);
  container.innerHTML = '';
  data.forEach(category => {
    const card = document.createElement('div');
    card.className = 'skill-card rounded-xl hover:scale-105 transition-transform';
    card.style.opacity = '1';
    card.style.display = 'block';
    card.innerHTML = `
      <i class="fas fa-${category.icon} mb-2"></i>
      <h3 class="mb-4">${category.title}</h3>
      <div class="space-y-3">
        ${category.skills.map(skill => `
          <div class="skill-item">
            <span>${skill.name}</span>
            <div class="progress-circle-container">
              <div class="progress-circle-bg"></div>
              <svg class="progress-circle">
                <circle cx="20" cy="20" r="18" stroke="#E5E5E5" stroke-width="4" fill="none" />
                <circle class="progress-fill" cx="20" cy="20" r="18" stroke="#1E90FF" stroke-width="4" fill="none" stroke-dasharray="0 113" />
              </svg>
              <span class="progress-percentage">${skill.proficiency}%</span>
            </div>
          </div>
        `).join('')}
      </div>
    `;
    container.appendChild(card);
    console.log(`Rendered skill card for ${category.title}`);
    card.querySelectorAll('.progress-fill').forEach(circle => {
      const proficiency = circle.parentElement.parentElement.querySelector('.progress-percentage').textContent.replace('%', '');
      const circumference = 2 * Math.PI * 18;
      const offset = circumference * (proficiency / 100);
      gsap.to(circle, {
        scrollTrigger: { 
          trigger: card, 
          start: 'left 80%',
          end: 'right 20%',
          scrub: true
        },
        strokeDasharray: `${offset} 113`,
        duration: 1.5,
        ease: 'power3.out'
      });
    });
  });
});

// Render Achievements
fetchData('/api/achievements', 'achievements-grid', (data, container) => {
  data.forEach(achievement => {
    const card = document.createElement('div');
    card.className = 'achievement-card glassmorphic p-6 rounded-xl hover:scale-105 transition-transform';
    card.setAttribute('data-tilt', '');
    card.setAttribute('data-tilt-max', '10');
    card.innerHTML = `
      <div class="flex items-start space-x-4">
        <div class="icon-wrapper p-3 glassmorphic rounded-full">
          <i class="fas fa-${achievement.icon} text-primary-blue glow"></i>
        </div>
        <div>
          <h3 class="text-lg font-orbitron text-primary-blue glow">${achievement.title}</h3>
          <p class="text-sm text-primary-blue">${achievement.organization}</p>
          <p class="text-gray-300">${achievement.description}</p>
        </div>
      </div>
    `;
    container.appendChild(card);
    VanillaTilt.init(card);
    gsap.from(card, { scrollTrigger: { trigger: card, start: 'top 80%' }, y: 50, opacity: 0, duration: 1, ease: 'power3.out' });
  });
});

// Render Hobbies with Review Form for "Educating Others"
fetchData('/api/hobbies', 'hobbies-grid', (data, container) => {
  data.forEach(hobby => {
    const card = document.createElement('div');
    card.className = 'hobby-card glassmorphic p-6 rounded-xl hover:scale-105 transition-transform';
    card.setAttribute('data-tilt', '');
    card.setAttribute('data-tilt-max', '10');
    card.innerHTML = `
      <div class="flex items-center space-x-4">
        <div class="icon-wrapper p-3 glassmorphic rounded-full">
          <i class="fas fa-${hobby.icon} text-primary-blue glow"></i>
        </div>
        <div>
          <h3 class="text-lg font-orbitron text-primary-blue glow">${hobby.title}</h3>
          <p class="text-gray-300">${hobby.description}</p>
        </div>
      </div>
    `;
    if (hobby.title === "Educating Others") {
      card.innerHTML += `
        <div class="mt-6">
          <h4 class="text-md font-orbitron text-primary-blue glow mb-4">Share Your Feedback</h4>
          <div class="glassmorphic p-6 rounded-xl space-y-4">
            <div>
              <label class="block text-sm text-gray-300 mb-2">Your Name</label>
              <input type="text" id="review-name" class="w-full p-3 rounded-md bg-transparent border border-gray-600 text-gray-100 focus:border-primary-blue focus:glow" placeholder="Enter your name">
            </div>
            <div>
              <label class="block text-sm text-gray-300 mb-2">Rating</label>
              <div id="star-rating" class="text-2xl text-gray-400 flex space-x-1">
                <span class="star cursor-pointer" data-value="1"><i class="far fa-star"></i></span>
                <span class="star cursor-pointer" data-value="2"><i class="far fa-star"></i></span>
                <span class="star cursor-pointer" data-value="3"><i class="far fa-star"></i></span>
                <span class="star cursor-pointer" data-value="4"><i class="far fa-star"></i></span>
                <span class="star cursor-pointer" data-value="5"><i class="far fa-star"></i></span>
              </div>
              <input type="hidden" id="review-rating" value="0">
            </div>
            <div>
              <label class="block text-sm text-gray-300 mb-2">Your Experience</label>
              <textarea id="review-description" class="w-full p-3 rounded-md bg-transparent border border-gray-600 text-gray-100 focus:border-primary-blue focus:glow" placeholder="Describe your learning experience..." rows="4"></textarea>
            </div>
            <button id="submit-review" class="btn btn-primary ripple w-full">Submit Feedback</button>
          </div>
          <div class="mt-6">
            <h4 class="text-md font-orbitron text-primary-blue glow mb-4">Testimonials</h4>
            <div id="reviews-container" class="space-y-4"></div>
          </div>
        </div>
      `;
    }
    container.appendChild(card);
    VanillaTilt.init(card);
    gsap.from(card, { scrollTrigger: { trigger: card, start: 'top 80%' }, y: 50, opacity: 0, duration: 1, ease: 'power3.out' });

    if (hobby.title === "Educating Others") {
      const stars = card.querySelectorAll('.star');
      const ratingInput = card.querySelector('#review-rating');
      stars.forEach(star => {
        star.addEventListener('click', () => {
          const rating = star.getAttribute('data-value');
          ratingInput.value = rating;
          stars.forEach(s => {
            const value = s.getAttribute('data-value');
            if (value <= rating) {
              s.innerHTML = '<i class="fas fa-star text-primary-blue glow"></i>';
            } else {
              s.innerHTML = '<i class="far fa-star text-gray-400"></i>';
            }
          });
        });
      });

      card.querySelector('#submit-review').addEventListener('click', () => {
        const name = card.querySelector('#review-name').value.trim();
        const rating = parseInt(card.querySelector('#review-rating').value);
        const description = card.querySelector('#review-description').value.trim();

        if (!name || rating === 0 || !description) {
          alert('Please fill out all fields and select a rating.');
          return;
        }

        fetch('/api/reviews', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ name, rating, description })
        })
        .then(response => response.json())
        .then(data => {
          if (data.message) {
            alert('Thank you for your feedback!');
            card.querySelector('#review-name').value = '';
            card.querySelector('#review-description').value = '';
            card.querySelector('#review-rating').value = '0';
            stars.forEach(star => star.innerHTML = '<i class="far fa-star text-gray-400"></i>');
            fetchReviews(card.querySelector('#reviews-container'));
          } else {
            alert('Error submitting feedback: ' + (data.error || 'Unknown error'));
          }
        })
        .catch(error => {
          console.error('Error submitting review:', error);
          alert('Error submitting feedback. Please try again later.');
        });
      });

      function fetchReviews(reviewsContainer) {
        fetch('/api/reviews')
          .then(response => response.json())
          .then(reviews => {
            reviewsContainer.innerHTML = '';
            if (reviews.length === 0) {
              reviewsContainer.innerHTML = '<p class="text-gray-400">No testimonials yet. Be the first to share your experience!</p>';
              return;
            }
            reviews.forEach(review => {
              const reviewDiv = document.createElement('div');
              reviewDiv.className = 'glassmorphic p-4 rounded-xl flex justify-between items-start';
              reviewDiv.innerHTML = `
                <div>
                  <div class="flex items-center mb-2">
                    <span class="font-orbitron text-primary-blue glow mr-2">${review.name}</span>
                    <div class="text-primary-blue flex">
                      ${'<i class="fas fa-star glow"></i>'.repeat(review.rating)}
                      ${'<i class="far fa-star text-gray-400"></i>'.repeat(5 - review.rating)}
                    </div>
                  </div>
                  <p class="text-gray-300 text-sm">${review.description}</p>
                </div>
                <button class="delete-review text-red-500 hover:text-red-700 glow" data-id="${review.id}">
                  <i class="fas fa-trash-alt"></i>
                </button>
              `;
              reviewsContainer.appendChild(reviewDiv);
              gsap.from(reviewDiv, { opacity: 0, y: 20, duration: 0.8, ease: 'power3.out' });

              reviewDiv.querySelector('.delete-review').addEventListener('click', () => {
                const confirmDelete = confirm(`Are you sure you want to delete the review by ${review.name}?`);
                if (confirmDelete) {
                  const password = prompt('Please enter the admin password to delete this review:');
                  if (!password) {
                    alert('Password is required to delete a review.');
                    return;
                  }

                  fetch(`/api/reviews/delete/${review.id}`, {
                    method: 'DELETE',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ password })
                  })
                  .then(response => response.json())
                  .then(data => {
                    if (data.message) {
                      alert(data.message);
                      fetchReviews(reviewsContainer);
                    } else {
                      alert('Error deleting review: ' + (data.error || 'Unknown error'));
                    }
                  })
                  .catch(error => {
                    console.error('Error deleting review:', error);
                    alert('Error deleting review. Please try again later.');
                  });
                }
              });
            });
          })
          .catch(error => {
            console.error('Error fetching reviews:', error);
            reviewsContainer.innerHTML = '<p class="text-red-500">Error loading testimonials. Please try again later.</p>';
          });
      }

      fetchReviews(card.querySelector('#reviews-container'));
    }
  });
});

// Render Projects with Modal
const modal = document.getElementById('project-modal');
const modalClose = document.getElementById('modal-close');
fetchData('/api/projects', 'projects-grid', (data, container) => {
  data.forEach(project => {
    const card = document.createElement('div');
    card.className = 'project-card glassmorphic rounded-xl overflow-hidden cursor-pointer hover:scale-105 transition-transform';
    card.setAttribute('data-tilt', '');
    card.setAttribute('data-tilt-max', '10');
    card.innerHTML = `
      <div class="relative">
        <img src="${project.image}" alt="${project.title}" class="w-full h-48 object-cover glow">
        <div class="project-overlay absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100">
          <i class="fas fa-search text-white text-2xl glow"></i>
        </div>
      </div>
      <div class="p-6">
        <h3 class="text-lg font-orbitron text-primary-blue glow mb-2">${project.title}</h3>
        <p class="text-gray-300 text-sm mb-4">${project.description.substring(0, 100)}...</p>
        <div class="flex flex-wrap gap-2">
          ${project.technologies.map(tech => `<span class="tech-tag glassmorphic text-xs px-2 py-1 rounded-full text-primary-blue glow">${tech}</span>`).join('')}
        </div>
      </div>
    `;
    card.addEventListener('click', () => {
      const mediaContainer = document.getElementById('modal-media');
      mediaContainer.innerHTML = project.video ? `
        <div class="video-container">
          <iframe src="${project.video}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen class="glow"></iframe>
        </div>
      ` : `<img src="${project.image}" alt="${project.title}" class="w-full h-48 sm:h-64 object-cover rounded-md glow">`;
      document.getElementById('modal-title').textContent = project.title;
      document.getElementById('modal-description').textContent = project.description;
      document.getElementById('modal-role').textContent = project.role;
      const contributionsContainer = document.getElementById('modal-contributions');
      contributionsContainer.innerHTML = project.contributions.map(contribution => `<li>${contribution}</li>`).join('');
      const techContainer = document.getElementById('modal-tech');
      techContainer.innerHTML = project.technologies.map(tech => `<span class="tech-tag glassmorphic text-xs px-2 py-1 rounded-full text-primary-blue glow">${tech}</span>`).join('');
      document.getElementById('modal-github').href = project.githubLink;
      document.getElementById('modal-live').href = project.liveLink;
      modal.classList.remove('hidden');
      gsap.from(modal.querySelector('div'), { y: 100, opacity: 0, duration: 0.8, ease: 'power3.out' });
    });
    container.appendChild(card);
    VanillaTilt.init(card);
    gsap.from(card, { scrollTrigger: { trigger: card, start: 'top 80%' }, y: 50, opacity: 0, duration: 1, ease: 'power3.out' });
  });
});
modalClose.addEventListener('click', () => {
  modal.classList.add('hidden');
});
modal.addEventListener('click', (e) => {
  if (e.target === modal) modal.classList.add('hidden');
});

// Render Education
fetchData('/api/education', 'education-grid', (data, container) => {
  data.forEach(edu => {
    const card = document.createElement('div');
    card.className = 'education-card glassmorphic p-6 rounded-xl hover:scale-105 transition-transform';
    card.setAttribute('data-tilt', '');
    card.setAttribute('data-tilt-max', '10');
    card.innerHTML = `
      <div class="flex items-start space-x-4">
        <div class="icon-wrapper p-3 glassmorphic rounded-full">
          <i class="fas fa-graduation-cap text-primary-blue glow"></i>
        </div>
        <div class="flex-1">
          <div class="flex items-center justify-between mb-2">
            <h3 class="text-lg font-orbitron text-primary-blue glow">${edu.degree}</h3>
            <div class="period flex items-center text-gray-400">
              <i class="fas fa-calendar mr-1"></i>
              <span>${edu.period}</span>
            </div>
          </div>
          <h4 class="text-primary-blue glow mb-2">${edu.institution}</h4>
          <p class="text-gray-300 mb-4">${edu.description}</p>
          <h5 class="font-orbitron text-primary-blue glow">Key Achievements:</h5>
          <ul class="list-disc pl-5 text-gray-300">
            ${edu.achievements.map(achievement => `<li>${achievement}</li>`).join('')}
          </ul>
        </div>
      </div>
    `;
    container.appendChild(card);
    VanillaTilt.init(card);
    gsap.from(card, { scrollTrigger: { trigger: card, start: 'top 80%' }, y: 50, opacity: 0, duration: 1, ease: 'power3.out' });
  });
});

// Render Certifications
fetchData('/api/certifications', 'certifications-grid', (data, container) => {
  data.forEach(cert => {
    const card = document.createElement('div');
    card.className = 'certification-card glassmorphic p-6 rounded-xl hover:scale-105 transition-transform';
    card.setAttribute('data-tilt', '');
    card.setAttribute('data-tilt-max', '10');
    card.innerHTML = `
      <div class="flex items-start space-x-4">
        <div class="icon-wrapper p-3 glassmorphic rounded-full">
          <i class="fas fa-certificate text-primary-blue glow"></i>
        </div>
        <div class="flex-1">
          <div class="flex items-center justify-between mb-2">
            <h3 class="text-lg font-orbitron text-primary-blue glow">${cert.title}</h3>
            <div class="period flex items-center text-gray-400">
              <i class="fas fa-calendar mr-1"></i>
              <span>${cert.year}</span>
            </div>
          </div>
          <h4 class="text-primary-blue glow mb-2">${cert.platform}</h4>
          <p class="text-gray-300 mb-4">${cert.description}</p>
          <img src="${cert.badge}" alt="${cert.title} badge" class="w-24 h-24 object-contain mb-4 glow">
          <a href="${cert.certificateLink}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary ripple text-sm">Verify Certificate</a>
        </div>
      </div>
    `;
    container.appendChild(card);
    VanillaTilt.init(card);
    gsap.from(card, { scrollTrigger: { trigger: card, start: 'top 80%' }, y: 50, opacity: 0, duration: 1, ease: 'power3.out' });
  });
});

// Render Volunteer Experience
fetchData('/api/volunteer', 'volunteer-grid', (data, container) => {
  data.forEach(vol => {
    const card = document.createElement('div');
    card.className = 'volunteer-card glassmorphic p-6 rounded-xl hover:scale-105 transition-transform';
    card.setAttribute('data-tilt', '');
    card.setAttribute('data-tilt-max', '10');
    card.innerHTML = `
      <div class="flex items-start space-x-4">
        <div class="icon-wrapper p-3 glassmorphic rounded-full">
          <i class="fas fa-hands-helping text-primary-blue glow"></i>
        </div>
        <div class="flex-1">
          <div class="flex items-center justify-between mb-2">
            <h3 class="text-lg font-orbitron text-primary-blue glow">${vol.role}</h3>
            <div class="period flex items-center text-gray-400">
              <i class="fas fa-calendar mr-1"></i>
              <span>${vol.period}</span>
            </div>
          </div>
          <h4 class="text-primary-blue glow mb-2">${vol.organization}</h4>
          <p class="text-gray-300 mb-4">${vol.description}</p>
          <h5 class="font-orbitron text-primary-blue glow">Contributions:</h5>
          <ul class="list-disc pl-5 text-gray-300">
            ${vol.contributions.map(contribution => `<li>${contribution}</li>`).join('')}
          </ul>
        </div>
      </div>
    `;
    container.appendChild(card);
    VanillaTilt.init(card);
    gsap.from(card, { scrollTrigger: { trigger: card, start: 'top 80%' }, y: 50, opacity: 0, duration: 1, ease: 'power3.out' });
  });
});

// Render Talks
fetchData('/api/talks', 'talks-grid', (data, container) => {
  data.forEach(talk => {
    const card = document.createElement('div');
    card.className = 'talk-card glassmorphic p-6 rounded-xl hover:scale-105 transition-transform';
    card.setAttribute('data-tilt', '');
    card.setAttribute('data-tilt-max', '10');
    card.innerHTML = `
      <div class="flex items-start space-x-4">
        <div class="icon-wrapper p-3 glassmorphic rounded-full">
          <i class="fas fa-microphone text-primary-blue glow"></i>
        </div>
        <div class="flex-1">
          <div class="flex items-center justify-between mb-2">
            <h3 class="text-lg font-orbitron text-primary-blue glow">${talk.title}</h3>
            <div class="date flex items-center text-gray-400">
              <i class="fas fa-calendar mr-1"></i>
              <span>${talk.date}</span>
            </div>
          </div>
          <h4 class="text-primary-blue glow mb-2">${talk.event}</h4>
          <p class="text-gray-300 mb-4">${talk.description}</p>
          ${talk.image ? `
            <div class="mb-4">
              <img src="${talk.image}" alt="${talk.title} thumbnail" class="w-full h-48 object-cover rounded-md glow">
            </div>
          ` : ''}
          <div class="video-container mb-4">
            <iframe src="${talk.videoLink}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen class="glow"></iframe>
          </div>
          <a href="${talk.videoLink}" target="_blank" rel="noopener noreferrer" class="btn btn-primary ripple text-sm">Watch Full Talk</a>
        </div>
      </div>
    `;
    container.appendChild(card);
    VanillaTilt.init(card);
    gsap.from(card, { scrollTrigger: { trigger: card, start: 'top 80%' }, y: 50, opacity: 0, duration: 1, ease: 'power3.out' });
  });
});

// Handle Contact Form Submission
const contactSubmitButton = document.getElementById('contact-submit');
const emailInput = document.getElementById('email');
const messageInput = document.getElementById('message');

contactSubmitButton.addEventListener('click', async () => {
  const email = emailInput.value.trim();
  const message = messageInput.value.trim();

  // Validate inputs
  if (!email || !message) {
    alert('Please fill in both email and message fields.');
    return;
  }

  if (!/\S+@\S+\.\S+/.test(email)) {
    alert('Please enter a valid email address.');
    return;
  }

  try {
    const response = await fetch('/api/contact', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, message })
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.error || `HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    alert(data.message);
    emailInput.value = '';
    messageInput.value = '';
  } catch (error) {
    console.error('Error submitting contact form:', error);
    alert('Error submitting form. If you\'re on Hugging Face Spaces, please use LinkedIn or GitHub to contact me.');
  }
});