ibrahimlasfar commited on
Commit
538e152
Β·
1 Parent(s): 018e5ef

Add MGZon logo to OAuth button

Browse files
Files changed (2) hide show
  1. public/images/mgzon-logo.png +0 -0
  2. views/index.ejs +385 -63
public/images/mgzon-logo.png ADDED
views/index.ejs CHANGED
@@ -5,21 +5,44 @@
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <meta name="description" content="Ibrahim Al-Asfar Portfolio API - Full-stack web developer portfolio backend API">
8
- <meta name="keywords" content="portfolio, API, Node.js, Express, MongoDB, developer">
9
  <meta name="author" content="Ibrahim Al-Asfar">
 
 
 
10
  <meta property="og:title" content="Ibrahim Al-Asfar Portfolio API">
11
- <meta property="og:description" content="Full-stack web developer portfolio API">
 
12
  <meta property="og:type" content="website">
13
- <title> Portfolio API</title>
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  <!-- Tailwind CSS -->
16
  <script src="https://cdn.tailwindcss.com"></script>
 
17
  <!-- Font Awesome -->
18
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
19
 
20
-
21
  <!-- Custom Styles -->
22
  <style>
 
 
 
 
 
 
23
  @keyframes fadeInUp {
24
  from {
25
  opacity: 0;
@@ -32,16 +55,39 @@
32
  }
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  .animate-fadeInUp {
36
  animation: fadeInUp 0.6s ease-out;
37
  }
38
 
 
 
 
 
39
  .gradient-bg {
40
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
41
  }
42
 
 
 
 
 
 
 
 
43
  .card-hover {
44
- transition: all 0.3s ease;
45
  }
46
 
47
  .card-hover:hover {
@@ -49,18 +95,29 @@
49
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
50
  }
51
 
 
 
 
 
 
 
 
 
 
 
52
  /* Custom scrollbar */
53
  ::-webkit-scrollbar {
54
- width: 8px;
55
  }
56
 
57
  ::-webkit-scrollbar-track {
58
  background: #f1f1f1;
 
59
  }
60
 
61
  ::-webkit-scrollbar-thumb {
62
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
63
- border-radius: 4px;
64
  }
65
 
66
  ::-webkit-scrollbar-thumb:hover {
@@ -69,13 +126,19 @@
69
 
70
  /* Logo styling */
71
  .logo-img {
72
- width: 32px;
73
- height: 32px;
74
  object-fit: contain;
75
- border-radius: 8px;
 
 
 
 
 
 
76
  }
77
 
78
- /* Fallback styles if Tailwind doesn't load */
79
  .bg-gradient-to-br {
80
  background: linear-gradient(to bottom right, #f9fafb, #f3f4f6);
81
  }
@@ -88,6 +151,10 @@
88
  border-radius: 0.5rem;
89
  }
90
 
 
 
 
 
91
  .p-2 {
92
  padding: 0.5rem;
93
  }
@@ -96,6 +163,10 @@
96
  padding: 0.75rem;
97
  }
98
 
 
 
 
 
99
  .p-5 {
100
  padding: 1.25rem;
101
  }
@@ -109,6 +180,11 @@
109
  padding-bottom: 2rem;
110
  }
111
 
 
 
 
 
 
112
  .py-16 {
113
  padding-top: 4rem;
114
  padding-bottom: 4rem;
@@ -124,6 +200,11 @@
124
  padding-right: 1rem;
125
  }
126
 
 
 
 
 
 
127
  .text-center {
128
  text-align: center;
129
  }
@@ -176,6 +257,10 @@
176
  background-color: #10b981;
177
  }
178
 
 
 
 
 
179
  .mb-2 {
180
  margin-bottom: 0.5rem;
181
  }
@@ -204,6 +289,10 @@
204
  margin-right: 0.5rem;
205
  }
206
 
 
 
 
 
207
  .flex {
208
  display: flex;
209
  }
@@ -261,6 +350,14 @@
261
  height: 3rem;
262
  }
263
 
 
 
 
 
 
 
 
 
264
  .w-3 {
265
  width: 0.75rem;
266
  }
@@ -273,8 +370,8 @@
273
  border-radius: 9999px;
274
  }
275
 
276
- .rounded-xl {
277
- border-radius: 0.75rem;
278
  }
279
 
280
  .animate-pulse {
@@ -334,8 +431,12 @@
334
  transition-duration: 150ms;
335
  }
336
 
337
- .hover\:shadow-lg:hover {
338
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
 
 
 
 
339
  }
340
 
341
  .hover\:bg-gray-900:hover {
@@ -346,6 +447,10 @@
346
  color: #7c3aed;
347
  }
348
 
 
 
 
 
349
  @media (min-width: 640px) {
350
  .sm\:px-6 {
351
  padding-left: 1.5rem;
@@ -362,6 +467,10 @@
362
  grid-template-columns: repeat(3, minmax(0, 1fr));
363
  }
364
 
 
 
 
 
365
  .md\:text-6xl {
366
  font-size: 3.75rem;
367
  }
@@ -372,27 +481,67 @@
372
  grid-template-columns: repeat(3, minmax(0, 1fr));
373
  }
374
 
 
 
 
 
375
  .lg\:px-8 {
376
  padding-left: 2rem;
377
  padding-right: 2rem;
378
  }
379
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  </style>
381
  </head>
382
 
383
  <body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen">
384
 
385
  <!-- Navigation -->
386
- <nav class="bg-white shadow-lg sticky top-0 z-50">
387
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
388
  <div class="flex justify-between items-center h-16">
389
  <div class="flex items-center space-x-3">
390
  <!-- Logo Image -->
391
- <img src="images/logo.png" alt="Logo" class="logo-img"
392
  onerror="this.onerror=null; this.parentElement.innerHTML='<div class=\'gradient-bg rounded-lg p-2\'><i class=\'fas fa-code text-white text-xl\'></i></div>'">
393
- <h1
394
- class="text-xl font-bold bg-gradient-to-r from-purple-600 to-blue-600 bg-clip-text text-transparent">
395
- Portfolio API
396
  </h1>
397
  </div>
398
  <div class="flex items-center space-x-4">
@@ -420,10 +569,9 @@
420
  <div class="text-center animate-fadeInUp">
421
  <div class="inline-flex items-center justify-center p-2 bg-green-100 rounded-full mb-4">
422
  <i class="fas fa-check-circle text-green-600 mr-2"></i>
423
- <span class="text-green-600 text-sm font-medium">API is running</span>
424
  </div>
425
- <h1
426
- class="text-5xl md:text-6xl font-bold bg-gradient-to-r from-purple-600 via-blue-600 to-purple-600 bg-clip-text text-transparent mb-6">
427
  Welcome to My Portfolio API
428
  </h1>
429
  <p class="text-xl text-gray-600 mb-8 max-w-2xl mx-auto">
@@ -432,14 +580,15 @@
432
  </p>
433
  <div class="flex flex-wrap justify-center gap-4">
434
  <a href="/api-docs"
435
- class="gradient-bg text-white px-8 py-3 rounded-lg font-semibold hover:shadow-lg transition-all inline-flex items-center">
436
  <i class="fas fa-rocket mr-2"></i>
437
  Explore API
438
  </a>
439
- <a href="https://github.com/Mark-Lasfar" target="_blank"
440
- class="bg-gray-800 text-white px-8 py-3 rounded-lg font-semibold hover:bg-gray-900 transition-all inline-flex items-center">
441
- <i class="fab fa-github mr-2"></i>
442
- GitHub
 
443
  </a>
444
  </div>
445
  </div>
@@ -456,7 +605,7 @@
456
  <h3 class="text-2xl font-bold text-gray-800 mb-2">Database Status</h3>
457
  <div class="flex items-center">
458
  <div class="w-3 h-3 bg-green-500 rounded-full animate-pulse mr-2"></div>
459
- <p class="text-gray-600" id="db-status">MongoDB Connected</p>
460
  </div>
461
  </div>
462
 
@@ -465,7 +614,7 @@
465
  <i class="fas fa-cloud-upload-alt text-white text-xl"></i>
466
  </div>
467
  <h3 class="text-2xl font-bold text-gray-800 mb-2">Cloudinary</h3>
468
- <p class="text-gray-600" id="cloudinary-status">Media Storage Active</p>
469
  </div>
470
 
471
  <div class="bg-white rounded-xl shadow-lg p-6 card-hover animate-fadeInUp" style="animation-delay: 0.3s">
@@ -473,67 +622,176 @@
473
  <i class="fas fa-chart-line text-white text-xl"></i>
474
  </div>
475
  <h3 class="text-2xl font-bold text-gray-800 mb-2">Analytics</h3>
476
- <p class="text-gray-600" id="sentry-status">Sentry Monitoring Active</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  </div>
478
  </div>
479
  </div>
480
 
481
  <!-- API Endpoints Section -->
482
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
483
- <h2 class="text-3xl font-bold text-center text-gray-800 mb-12">API Endpoints</h2>
484
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
485
- <div class="bg-white rounded-lg shadow-md p-5 hover:shadow-lg transition">
486
  <div class="flex items-center justify-between mb-3">
487
  <span class="bg-green-100 text-green-600 text-xs font-semibold px-2 py-1 rounded">GET</span>
488
  <i class="fas fa-users text-gray-400"></i>
489
  </div>
490
  <code class="text-sm text-gray-700">/api/projects</code>
491
  <p class="text-gray-500 text-sm mt-2">Get all public projects</p>
 
 
492
  </div>
493
 
494
- <div class="bg-white rounded-lg shadow-md p-5 hover:shadow-lg transition">
495
  <div class="flex items-center justify-between mb-3">
496
  <span class="bg-green-100 text-green-600 text-xs font-semibold px-2 py-1 rounded">GET</span>
497
  <i class="fas fa-chart-simple text-gray-400"></i>
498
  </div>
499
  <code class="text-sm text-gray-700">/api/skills</code>
500
  <p class="text-gray-500 text-sm mt-2">Get all skills</p>
 
 
501
  </div>
502
 
503
- <div class="bg-white rounded-lg shadow-md p-5 hover:shadow-lg transition">
504
  <div class="flex items-center justify-between mb-3">
505
  <span class="bg-green-100 text-green-600 text-xs font-semibold px-2 py-1 rounded">GET</span>
506
  <i class="fas fa-heart text-gray-400"></i>
507
  </div>
508
  <code class="text-sm text-gray-700">/api/health</code>
509
  <p class="text-gray-500 text-sm mt-2">Check system health</p>
 
 
510
  </div>
511
 
512
- <div class="bg-white rounded-lg shadow-md p-5 hover:shadow-lg transition">
513
  <div class="flex items-center justify-between mb-3">
514
  <span class="bg-blue-100 text-blue-600 text-xs font-semibold px-2 py-1 rounded">POST</span>
515
  <i class="fas fa-user-plus text-gray-400"></i>
516
  </div>
517
  <code class="text-sm text-gray-700">/api/register</code>
518
  <p class="text-gray-500 text-sm mt-2">Create new account</p>
 
 
 
519
  </div>
520
 
521
- <div class="bg-white rounded-lg shadow-md p-5 hover:shadow-lg transition">
522
  <div class="flex items-center justify-between mb-3">
523
  <span class="bg-blue-100 text-blue-600 text-xs font-semibold px-2 py-1 rounded">POST</span>
524
  <i class="fas fa-sign-in-alt text-gray-400"></i>
525
  </div>
526
  <code class="text-sm text-gray-700">/api/login</code>
527
  <p class="text-gray-500 text-sm mt-2">Authenticate user</p>
 
 
528
  </div>
529
 
530
- <div class="bg-white rounded-lg shadow-md p-5 hover:shadow-lg transition">
531
  <div class="flex items-center justify-between mb-3">
532
- <span class="bg-purple-100 text-purple-600 text-xs font-semibold px-2 py-1 rounded">AUTH</span>
533
  <i class="fab fa-google text-gray-400"></i>
534
  </div>
535
  <code class="text-sm text-gray-700">/auth/google</code>
536
- <p class="text-gray-500 text-sm mt-2">Google OAuth</p>
 
 
537
  </div>
538
  </div>
539
  </div>
@@ -541,7 +799,7 @@
541
  <!-- Tech Stack Section -->
542
  <div class="bg-white py-16">
543
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
544
- <h2 class="text-3xl font-bold text-center text-gray-800 mb-12">Technology Stack</h2>
545
  <div class="flex flex-wrap justify-center gap-8">
546
  <div class="text-center">
547
  <i class="fab fa-node-js text-5xl text-green-600"></i>
@@ -559,7 +817,6 @@
559
  <i class="fas fa-project-diagram text-5xl text-pink-500"></i>
560
  <p class="mt-2 text-gray-600">GraphQL</p>
561
  </div>
562
-
563
  <div class="text-center">
564
  <i class="fab fa-docker text-5xl text-blue-600"></i>
565
  <p class="mt-2 text-gray-600">Docker</p>
@@ -568,6 +825,14 @@
568
  <i class="fab fa-aws text-5xl text-orange-500"></i>
569
  <p class="mt-2 text-gray-600">AWS</p>
570
  </div>
 
 
 
 
 
 
 
 
571
  </div>
572
  </div>
573
  </div>
@@ -583,7 +848,46 @@
583
  </div>
584
  </footer>
585
 
 
 
 
586
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  // Fetch real-time data
588
  async function fetchStats() {
589
  try {
@@ -591,25 +895,42 @@
591
  const data = await response.json();
592
  console.log('System Health:', data);
593
 
594
- // Update statuses based on real data
595
- if (data.mongodb === 'connected') {
596
- document.getElementById('db-status').innerHTML = 'MongoDB Connected βœ…';
597
- document.getElementById('db-status').className = 'text-green-600';
598
- }
599
- if (data.cloudinary === 'configured') {
600
- document.getElementById('cloudinary-status').innerHTML = 'Cloudinary Active βœ…';
601
- document.getElementById('cloudinary-status').className = 'text-green-600';
602
- }
603
- if (data.sentry === 'configured') {
604
- document.getElementById('sentry-status').innerHTML = 'Sentry Active βœ…';
605
- document.getElementById('sentry-status').className = 'text-green-600';
606
- }
607
  } catch (error) {
608
  console.error('Error fetching stats:', error);
609
  document.getElementById('db-status').innerHTML = 'Connection Error ❌';
610
  document.getElementById('db-status').className = 'text-red-600';
 
611
  }
612
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  fetchStats();
614
 
615
  // Refresh stats every 30 seconds
@@ -622,14 +943,10 @@
622
  document.documentElement.classList.remove('dark');
623
  }
624
 
625
- // Add smooth scroll behavior
626
- document.querySelectorAll('a[href^="#"]').forEach(anchor => {
627
- anchor.addEventListener('click', function (e) {
628
- e.preventDefault();
629
- document.querySelector(this.getAttribute('href')).scrollIntoView({
630
- behavior: 'smooth'
631
- });
632
- });
633
  });
634
 
635
  // Add page load animation
@@ -640,6 +957,11 @@
640
  document.body.style.opacity = '1';
641
  }, 100);
642
  });
 
 
 
 
 
643
  </script>
644
  </body>
645
 
 
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <meta name="description" content="Ibrahim Al-Asfar Portfolio API - Full-stack web developer portfolio backend API">
8
+ <meta name="keywords" content="portfolio, API, Node.js, Express, MongoDB, developer, OAuth, JWT">
9
  <meta name="author" content="Ibrahim Al-Asfar">
10
+ <meta name="robots" content="index, follow">
11
+
12
+ <!-- Open Graph / Social Media -->
13
  <meta property="og:title" content="Ibrahim Al-Asfar Portfolio API">
14
+ <meta property="og:description"
15
+ content="Full-stack web developer portfolio API with authentication and AI features">
16
  <meta property="og:type" content="website">
17
+ <meta property="og:url" content="https://mgzon-server.hf.space">
18
+ <meta property="og:image" content="https://mgzon-server.hf.space/images/logo.png">
19
+
20
+ <!-- Twitter Card -->
21
+ <meta name="twitter:card" content="summary_large_image">
22
+ <meta name="twitter:title" content="Ibrahim Al-Asfar Portfolio API">
23
+ <meta name="twitter:description" content="Full-stack web developer portfolio API">
24
+ <meta name="twitter:image" content="https://mgzon-server.hf.space/images/logo.png">
25
+
26
+ <!-- Favicon -->
27
+ <link rel="icon" type="image/png" href="/images/logo.png">
28
+ <link rel="apple-touch-icon" href="/images/logo.png">
29
+
30
+ <title>Ibrahim Al-Asfar Portfolio API</title>
31
 
32
  <!-- Tailwind CSS -->
33
  <script src="https://cdn.tailwindcss.com"></script>
34
+
35
  <!-- Font Awesome -->
36
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
37
 
 
38
  <!-- Custom Styles -->
39
  <style>
40
+ * {
41
+ margin: 0;
42
+ padding: 0;
43
+ box-sizing: border-box;
44
+ }
45
+
46
  @keyframes fadeInUp {
47
  from {
48
  opacity: 0;
 
55
  }
56
  }
57
 
58
+ @keyframes float {
59
+
60
+ 0%,
61
+ 100% {
62
+ transform: translateY(0px);
63
+ }
64
+
65
+ 50% {
66
+ transform: translateY(-10px);
67
+ }
68
+ }
69
+
70
  .animate-fadeInUp {
71
  animation: fadeInUp 0.6s ease-out;
72
  }
73
 
74
+ .animate-float {
75
+ animation: float 3s ease-in-out infinite;
76
+ }
77
+
78
  .gradient-bg {
79
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
80
  }
81
 
82
+ .gradient-text {
83
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
84
+ -webkit-background-clip: text;
85
+ -webkit-text-fill-color: transparent;
86
+ background-clip: text;
87
+ }
88
+
89
  .card-hover {
90
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
91
  }
92
 
93
  .card-hover:hover {
 
95
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
96
  }
97
 
98
+ .btn-hover {
99
+ transition: all 0.3s ease;
100
+ position: relative;
101
+ overflow: hidden;
102
+ }
103
+
104
+ .btn-hover:hover {
105
+ transform: scale(1.05);
106
+ }
107
+
108
  /* Custom scrollbar */
109
  ::-webkit-scrollbar {
110
+ width: 10px;
111
  }
112
 
113
  ::-webkit-scrollbar-track {
114
  background: #f1f1f1;
115
+ border-radius: 10px;
116
  }
117
 
118
  ::-webkit-scrollbar-thumb {
119
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
120
+ border-radius: 10px;
121
  }
122
 
123
  ::-webkit-scrollbar-thumb:hover {
 
126
 
127
  /* Logo styling */
128
  .logo-img {
129
+ width: 40px;
130
+ height: 40px;
131
  object-fit: contain;
132
+ border-radius: 10px;
133
+ }
134
+
135
+ /* Glass effect */
136
+ .glass-card {
137
+ background: rgba(255, 255, 255, 0.9);
138
+ backdrop-filter: blur(10px);
139
  }
140
 
141
+ /* Fallback styles */
142
  .bg-gradient-to-br {
143
  background: linear-gradient(to bottom right, #f9fafb, #f3f4f6);
144
  }
 
151
  border-radius: 0.5rem;
152
  }
153
 
154
+ .rounded-xl {
155
+ border-radius: 0.75rem;
156
+ }
157
+
158
  .p-2 {
159
  padding: 0.5rem;
160
  }
 
163
  padding: 0.75rem;
164
  }
165
 
166
+ .p-4 {
167
+ padding: 1rem;
168
+ }
169
+
170
  .p-5 {
171
  padding: 1.25rem;
172
  }
 
180
  padding-bottom: 2rem;
181
  }
182
 
183
+ .py-12 {
184
+ padding-top: 3rem;
185
+ padding-bottom: 3rem;
186
+ }
187
+
188
  .py-16 {
189
  padding-top: 4rem;
190
  padding-bottom: 4rem;
 
200
  padding-right: 1rem;
201
  }
202
 
203
+ .px-8 {
204
+ padding-left: 2rem;
205
+ padding-right: 2rem;
206
+ }
207
+
208
  .text-center {
209
  text-align: center;
210
  }
 
257
  background-color: #10b981;
258
  }
259
 
260
+ .bg-red-500 {
261
+ background-color: #ef4444;
262
+ }
263
+
264
  .mb-2 {
265
  margin-bottom: 0.5rem;
266
  }
 
289
  margin-right: 0.5rem;
290
  }
291
 
292
+ .ml-2 {
293
+ margin-left: 0.5rem;
294
+ }
295
+
296
  .flex {
297
  display: flex;
298
  }
 
350
  height: 3rem;
351
  }
352
 
353
+ .w-16 {
354
+ width: 4rem;
355
+ }
356
+
357
+ .h-16 {
358
+ height: 4rem;
359
+ }
360
+
361
  .w-3 {
362
  width: 0.75rem;
363
  }
 
370
  border-radius: 9999px;
371
  }
372
 
373
+ .cursor-pointer {
374
+ cursor: pointer;
375
  }
376
 
377
  .animate-pulse {
 
431
  transition-duration: 150ms;
432
  }
433
 
434
+ .hover\:shadow-xl:hover {
435
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
436
+ }
437
+
438
+ .hover\:shadow-2xl:hover {
439
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
440
  }
441
 
442
  .hover\:bg-gray-900:hover {
 
447
  color: #7c3aed;
448
  }
449
 
450
+ .hover\:scale-105:hover {
451
+ transform: scale(1.05);
452
+ }
453
+
454
  @media (min-width: 640px) {
455
  .sm\:px-6 {
456
  padding-left: 1.5rem;
 
467
  grid-template-columns: repeat(3, minmax(0, 1fr));
468
  }
469
 
470
+ .md\:grid-cols-4 {
471
+ grid-template-columns: repeat(4, minmax(0, 1fr));
472
+ }
473
+
474
  .md\:text-6xl {
475
  font-size: 3.75rem;
476
  }
 
481
  grid-template-columns: repeat(3, minmax(0, 1fr));
482
  }
483
 
484
+ .lg\:grid-cols-4 {
485
+ grid-template-columns: repeat(4, minmax(0, 1fr));
486
+ }
487
+
488
  .lg\:px-8 {
489
  padding-left: 2rem;
490
  padding-right: 2rem;
491
  }
492
  }
493
+
494
+ /* Toast notification */
495
+ .toast {
496
+ position: fixed;
497
+ bottom: 20px;
498
+ right: 20px;
499
+ background: white;
500
+ border-radius: 8px;
501
+ padding: 12px 20px;
502
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
503
+ z-index: 1000;
504
+ animation: slideIn 0.3s ease;
505
+ }
506
+
507
+ @keyframes slideIn {
508
+ from {
509
+ transform: translateX(100%);
510
+ opacity: 0;
511
+ }
512
+
513
+ to {
514
+ transform: translateX(0);
515
+ opacity: 1;
516
+ }
517
+ }
518
+
519
+ .toast.success {
520
+ border-left: 4px solid #10b981;
521
+ }
522
+
523
+ .toast.error {
524
+ border-left: 4px solid #ef4444;
525
+ }
526
+
527
+ .toast.info {
528
+ border-left: 4px solid #3b82f6;
529
+ }
530
  </style>
531
  </head>
532
 
533
  <body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen">
534
 
535
  <!-- Navigation -->
536
+ <nav class="bg-white/90 backdrop-blur-md shadow-lg sticky top-0 z-50">
537
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
538
  <div class="flex justify-between items-center h-16">
539
  <div class="flex items-center space-x-3">
540
  <!-- Logo Image -->
541
+ <img src="/images/logo.png" alt="Logo" class="logo-img"
542
  onerror="this.onerror=null; this.parentElement.innerHTML='<div class=\'gradient-bg rounded-lg p-2\'><i class=\'fas fa-code text-white text-xl\'></i></div>'">
543
+ <h1 class="text-xl font-bold gradient-text">
544
+ Ibrahim Al-Asfar Portfolio
 
545
  </h1>
546
  </div>
547
  <div class="flex items-center space-x-4">
 
569
  <div class="text-center animate-fadeInUp">
570
  <div class="inline-flex items-center justify-center p-2 bg-green-100 rounded-full mb-4">
571
  <i class="fas fa-check-circle text-green-600 mr-2"></i>
572
+ <span class="text-green-600 text-sm font-medium" id="api-status">API is running</span>
573
  </div>
574
+ <h1 class="text-5xl md:text-6xl font-bold gradient-text mb-6">
 
575
  Welcome to My Portfolio API
576
  </h1>
577
  <p class="text-xl text-gray-600 mb-8 max-w-2xl mx-auto">
 
580
  </p>
581
  <div class="flex flex-wrap justify-center gap-4">
582
  <a href="/api-docs"
583
+ class="gradient-bg text-white px-8 py-3 rounded-lg font-semibold btn-hover inline-flex items-center">
584
  <i class="fas fa-rocket mr-2"></i>
585
  Explore API
586
  </a>
587
+ <a href="#test-api"
588
+ class="bg-gray-800 text-white px-8 py-3 rounded-lg font-semibold btn-hover inline-flex items-center"
589
+ id="test-api-btn">
590
+ <i class="fas fa-vial mr-2"></i>
591
+ Test API
592
  </a>
593
  </div>
594
  </div>
 
605
  <h3 class="text-2xl font-bold text-gray-800 mb-2">Database Status</h3>
606
  <div class="flex items-center">
607
  <div class="w-3 h-3 bg-green-500 rounded-full animate-pulse mr-2"></div>
608
+ <p class="text-gray-600" id="db-status">Checking...</p>
609
  </div>
610
  </div>
611
 
 
614
  <i class="fas fa-cloud-upload-alt text-white text-xl"></i>
615
  </div>
616
  <h3 class="text-2xl font-bold text-gray-800 mb-2">Cloudinary</h3>
617
+ <p class="text-gray-600" id="cloudinary-status">Checking...</p>
618
  </div>
619
 
620
  <div class="bg-white rounded-xl shadow-lg p-6 card-hover animate-fadeInUp" style="animation-delay: 0.3s">
 
622
  <i class="fas fa-chart-line text-white text-xl"></i>
623
  </div>
624
  <h3 class="text-2xl font-bold text-gray-800 mb-2">Analytics</h3>
625
+ <p class="text-gray-600" id="sentry-status">Checking...</p>
626
+ </div>
627
+ </div>
628
+ </div>
629
+
630
+ <!-- OAuth Authentication Section -->
631
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
632
+ <h2 class="text-3xl font-bold text-center text-gray-800 mb-12">πŸ” Authentication Providers</h2>
633
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
634
+ <!-- Google OAuth -->
635
+ <a href="/auth/google" class="bg-white rounded-xl shadow-lg p-6 card-hover text-center group"
636
+ target="_blank">
637
+ <div class="w-16 h-16 mx-auto mb-4">
638
+ <i class="fab fa-google text-5xl text-red-500 group-hover:scale-110 transition-transform"></i>
639
+ </div>
640
+ <h3 class="font-semibold text-gray-800">Sign in with Google</h3>
641
+ <p class="text-xs text-gray-500 mt-2">OAuth 2.0</p>
642
+ <span
643
+ class="inline-block mt-3 text-purple-600 text-sm opacity-0 group-hover:opacity-100 transition">Click
644
+ to test β†’</span>
645
+ </a>
646
+
647
+ <!-- Facebook OAuth -->
648
+ <a href="/auth/facebook" class="bg-white rounded-xl shadow-lg p-6 card-hover text-center group"
649
+ target="_blank">
650
+ <div class="w-16 h-16 mx-auto mb-4">
651
+ <i class="fab fa-facebook text-5xl text-blue-600 group-hover:scale-110 transition-transform"></i>
652
+ </div>
653
+ <h3 class="font-semibold text-gray-800">Sign in with Facebook</h3>
654
+ <p class="text-xs text-gray-500 mt-2">OAuth 2.0</p>
655
+ <span
656
+ class="inline-block mt-3 text-purple-600 text-sm opacity-0 group-hover:opacity-100 transition">Click
657
+ to test β†’</span>
658
+ </a>
659
+
660
+ <!-- GitHub OAuth -->
661
+ <a href="/auth/github" class="bg-white rounded-xl shadow-lg p-6 card-hover text-center group"
662
+ target="_blank">
663
+ <div class="w-16 h-16 mx-auto mb-4">
664
+ <i class="fab fa-github text-5xl text-gray-800 group-hover:scale-110 transition-transform"></i>
665
+ </div>
666
+ <h3 class="font-semibold text-gray-800">Sign in with GitHub</h3>
667
+ <p class="text-xs text-gray-500 mt-2">OAuth 2.0</p>
668
+ <span
669
+ class="inline-block mt-3 text-purple-600 text-sm opacity-0 group-hover:opacity-100 transition">Click
670
+ to test β†’</span>
671
+ </a>
672
+
673
+ <!-- MGZon OAuth -->
674
+ <a href="/auth/mgz" class="bg-white rounded-xl shadow-lg p-6 card-hover text-center group" target="_blank">
675
+ <div class="w-16 h-16 mx-auto mb-4">
676
+ <img src="https://mgzon-server.hf.space/images/logo.png" alt="MGZon"
677
+ class="w-16 h-16 rounded-full mx-auto group-hover:scale-110 transition-transform"
678
+ onerror="this.onerror=null; this.parentElement.innerHTML='<div class=\'w-16 h-16 gradient-bg rounded-full flex items-center justify-center mx-auto group-hover:scale-110 transition-transform\'><i class=\'fas fa-globe text-white text-2xl\'></i></div>'">
679
+ </div>
680
+ <h3 class="font-semibold text-gray-800">Sign in with MGZon</h3>
681
+ <p class="text-xs text-gray-500 mt-2">OAuth 2.0</p>
682
+ <span
683
+ class="inline-block mt-3 text-purple-600 text-sm opacity-0 group-hover:opacity-100 transition">Click
684
+ to test β†’</span>
685
+ </a>
686
+ </div>
687
+ </div>
688
+
689
+ <!-- API Test Section -->
690
+ <div id="test-api" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
691
+ <h2 class="text-3xl font-bold text-center text-gray-800 mb-12">πŸ§ͺ API Test Panel</h2>
692
+ <div class="bg-white rounded-xl shadow-lg p-6">
693
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
694
+ <div>
695
+ <label class="block text-sm font-medium text-gray-700 mb-2">Endpoint</label>
696
+ <select id="api-endpoint"
697
+ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent">
698
+ <option value="/api/health">GET /api/health</option>
699
+ <option value="/api/projects">GET /api/projects</option>
700
+ <option value="/api/skills">GET /api/skills</option>
701
+ <option value="/api/register">POST /api/register</option>
702
+ <option value="/api/login">POST /api/login</option>
703
+ </select>
704
+ </div>
705
+ <div>
706
+ <label class="block text-sm font-medium text-gray-700 mb-2">Request Body (JSON)</label>
707
+ <textarea id="api-body" rows="3"
708
+ class="w-full px-4 py-2 border border-gray-300 rounded-lg font-mono text-sm"
709
+ placeholder='{"email": "test@example.com", "password": "12345678"}'></textarea>
710
+ </div>
711
+ </div>
712
+ <div class="mt-4 flex justify-center">
713
+ <button id="send-request" class="gradient-bg text-white px-8 py-2 rounded-lg font-semibold btn-hover">
714
+ <i class="fas fa-paper-plane mr-2"></i>
715
+ Send Request
716
+ </button>
717
+ </div>
718
+ <div class="mt-6">
719
+ <label class="block text-sm font-medium text-gray-700 mb-2">Response</label>
720
+ <pre id="api-response"
721
+ class="bg-gray-900 text-green-400 p-4 rounded-lg overflow-x-auto font-mono text-sm max-h-96">Click "Send Request" to test API...</pre>
722
  </div>
723
  </div>
724
  </div>
725
 
726
  <!-- API Endpoints Section -->
727
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
728
+ <h2 class="text-3xl font-bold text-center text-gray-800 mb-12">πŸ“‘ API Endpoints</h2>
729
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
730
+ <div class="bg-white rounded-lg shadow-md p-5 card-hover">
731
  <div class="flex items-center justify-between mb-3">
732
  <span class="bg-green-100 text-green-600 text-xs font-semibold px-2 py-1 rounded">GET</span>
733
  <i class="fas fa-users text-gray-400"></i>
734
  </div>
735
  <code class="text-sm text-gray-700">/api/projects</code>
736
  <p class="text-gray-500 text-sm mt-2">Get all public projects</p>
737
+ <button onclick="testEndpoint('/api/projects')"
738
+ class="mt-3 text-purple-600 text-sm hover:underline">Test β†’</button>
739
  </div>
740
 
741
+ <div class="bg-white rounded-lg shadow-md p-5 card-hover">
742
  <div class="flex items-center justify-between mb-3">
743
  <span class="bg-green-100 text-green-600 text-xs font-semibold px-2 py-1 rounded">GET</span>
744
  <i class="fas fa-chart-simple text-gray-400"></i>
745
  </div>
746
  <code class="text-sm text-gray-700">/api/skills</code>
747
  <p class="text-gray-500 text-sm mt-2">Get all skills</p>
748
+ <button onclick="testEndpoint('/api/skills')" class="mt-3 text-purple-600 text-sm hover:underline">Test
749
+ β†’</button>
750
  </div>
751
 
752
+ <div class="bg-white rounded-lg shadow-md p-5 card-hover">
753
  <div class="flex items-center justify-between mb-3">
754
  <span class="bg-green-100 text-green-600 text-xs font-semibold px-2 py-1 rounded">GET</span>
755
  <i class="fas fa-heart text-gray-400"></i>
756
  </div>
757
  <code class="text-sm text-gray-700">/api/health</code>
758
  <p class="text-gray-500 text-sm mt-2">Check system health</p>
759
+ <button onclick="testEndpoint('/api/health')" class="mt-3 text-purple-600 text-sm hover:underline">Test
760
+ β†’</button>
761
  </div>
762
 
763
+ <div class="bg-white rounded-lg shadow-md p-5 card-hover">
764
  <div class="flex items-center justify-between mb-3">
765
  <span class="bg-blue-100 text-blue-600 text-xs font-semibold px-2 py-1 rounded">POST</span>
766
  <i class="fas fa-user-plus text-gray-400"></i>
767
  </div>
768
  <code class="text-sm text-gray-700">/api/register</code>
769
  <p class="text-gray-500 text-sm mt-2">Create new account</p>
770
+ <button
771
+ onclick="testEndpoint('/api/register', 'POST', {email: 'test@example.com', password: '12345678', username: 'testuser'})"
772
+ class="mt-3 text-purple-600 text-sm hover:underline">Test β†’</button>
773
  </div>
774
 
775
+ <div class="bg-white rounded-lg shadow-md p-5 card-hover">
776
  <div class="flex items-center justify-between mb-3">
777
  <span class="bg-blue-100 text-blue-600 text-xs font-semibold px-2 py-1 rounded">POST</span>
778
  <i class="fas fa-sign-in-alt text-gray-400"></i>
779
  </div>
780
  <code class="text-sm text-gray-700">/api/login</code>
781
  <p class="text-gray-500 text-sm mt-2">Authenticate user</p>
782
+ <button onclick="testEndpoint('/api/login', 'POST', {email: 'admin@elasfar.com', password: 'admin123'})"
783
+ class="mt-3 text-purple-600 text-sm hover:underline">Test β†’</button>
784
  </div>
785
 
786
+ <div class="bg-white rounded-lg shadow-md p-5 card-hover">
787
  <div class="flex items-center justify-between mb-3">
788
+ <span class="bg-purple-100 text-purple-600 text-xs font-semibold px-2 py-1 rounded">GET</span>
789
  <i class="fab fa-google text-gray-400"></i>
790
  </div>
791
  <code class="text-sm text-gray-700">/auth/google</code>
792
+ <p class="text-gray-500 text-sm mt-2">Google OAuth Login</p>
793
+ <a href="/auth/google" target="_blank"
794
+ class="mt-3 text-purple-600 text-sm hover:underline inline-block">Open β†’</a>
795
  </div>
796
  </div>
797
  </div>
 
799
  <!-- Tech Stack Section -->
800
  <div class="bg-white py-16">
801
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
802
+ <h2 class="text-3xl font-bold text-center text-gray-800 mb-12">⚑ Technology Stack</h2>
803
  <div class="flex flex-wrap justify-center gap-8">
804
  <div class="text-center">
805
  <i class="fab fa-node-js text-5xl text-green-600"></i>
 
817
  <i class="fas fa-project-diagram text-5xl text-pink-500"></i>
818
  <p class="mt-2 text-gray-600">GraphQL</p>
819
  </div>
 
820
  <div class="text-center">
821
  <i class="fab fa-docker text-5xl text-blue-600"></i>
822
  <p class="mt-2 text-gray-600">Docker</p>
 
825
  <i class="fab fa-aws text-5xl text-orange-500"></i>
826
  <p class="mt-2 text-gray-600">AWS</p>
827
  </div>
828
+ <div class="text-center">
829
+ <i class="fas fa-shield-alt text-5xl text-purple-600"></i>
830
+ <p class="mt-2 text-gray-600">JWT Auth</p>
831
+ </div>
832
+ <div class="text-center">
833
+ <i class="fas fa-cloud-upload-alt text-5xl text-blue-400"></i>
834
+ <p class="mt-2 text-gray-600">Cloudinary</p>
835
+ </div>
836
  </div>
837
  </div>
838
  </div>
 
848
  </div>
849
  </footer>
850
 
851
+ <!-- Toast Container -->
852
+ <div id="toast-container" class="fixed bottom-4 right-4 z-50"></div>
853
+
854
  <script>
855
+ // Show toast notification
856
+ function showToast(message, type = 'success') {
857
+ const container = document.getElementById('toast-container');
858
+ const toast = document.createElement('div');
859
+ toast.className = `toast ${type} mb-2`;
860
+ toast.innerHTML = `
861
+ <div class="flex items-center gap-3">
862
+ <i class="fas ${type === 'success' ? 'fa-check-circle text-green-500' : type === 'error' ? 'fa-exclamation-circle text-red-500' : 'fa-info-circle text-blue-500'}"></i>
863
+ <span>${message}</span>
864
+ </div>
865
+ `;
866
+ container.appendChild(toast);
867
+ setTimeout(() => toast.remove(), 3000);
868
+ }
869
+
870
+ // Test API endpoint
871
+ async function testEndpoint(url, method = 'GET', body = null) {
872
+ const responseDiv = document.getElementById('api-response');
873
+ responseDiv.textContent = 'Loading...';
874
+
875
+ try {
876
+ const options = { method, headers: { 'Content-Type': 'application/json' } };
877
+ if (body && method !== 'GET') {
878
+ options.body = JSON.stringify(body);
879
+ }
880
+
881
+ const response = await fetch(url, options);
882
+ const data = await response.json();
883
+ responseDiv.textContent = JSON.stringify(data, null, 2);
884
+ showToast(`βœ… ${url} - Status: ${response.status}`, 'success');
885
+ } catch (error) {
886
+ responseDiv.textContent = `Error: ${error.message}`;
887
+ showToast(`❌ ${url} - ${error.message}`, 'error');
888
+ }
889
+ }
890
+
891
  // Fetch real-time data
892
  async function fetchStats() {
893
  try {
 
895
  const data = await response.json();
896
  console.log('System Health:', data);
897
 
898
+ document.getElementById('db-status').innerHTML = data.mongodb === 'connected' ? 'MongoDB Connected βœ…' : 'MongoDB Error ❌';
899
+ document.getElementById('db-status').className = data.mongodb === 'connected' ? 'text-green-600' : 'text-red-600';
900
+
901
+ document.getElementById('cloudinary-status').innerHTML = data.cloudinary === 'configured' ? 'Cloudinary Active βœ…' : 'Cloudinary Not Configured ⚠️';
902
+ document.getElementById('cloudinary-status').className = data.cloudinary === 'configured' ? 'text-green-600' : 'text-yellow-600';
903
+
904
+ document.getElementById('sentry-status').innerHTML = data.sentry === 'configured' ? 'Sentry Active βœ…' : 'Sentry Not Configured ⚠️';
905
+ document.getElementById('sentry-status').className = data.sentry === 'configured' ? 'text-green-600' : 'text-yellow-600';
 
 
 
 
 
906
  } catch (error) {
907
  console.error('Error fetching stats:', error);
908
  document.getElementById('db-status').innerHTML = 'Connection Error ❌';
909
  document.getElementById('db-status').className = 'text-red-600';
910
+ showToast('Failed to fetch system health', 'error');
911
  }
912
  }
913
+
914
+ // API Test Panel
915
+ document.getElementById('send-request')?.addEventListener('click', async () => {
916
+ const endpoint = document.getElementById('api-endpoint').value;
917
+ const bodyText = document.getElementById('api-body').value;
918
+ let body = null;
919
+
920
+ if (bodyText && (endpoint.includes('/register') || endpoint.includes('/login'))) {
921
+ try {
922
+ body = JSON.parse(bodyText);
923
+ } catch (e) {
924
+ showToast('Invalid JSON format', 'error');
925
+ return;
926
+ }
927
+ }
928
+
929
+ const method = endpoint.includes('/register') || endpoint.includes('/login') ? 'POST' : 'GET';
930
+ await testEndpoint(endpoint, method, body);
931
+ });
932
+
933
+ // Load stats on page load
934
  fetchStats();
935
 
936
  // Refresh stats every 30 seconds
 
943
  document.documentElement.classList.remove('dark');
944
  }
945
 
946
+ // Scroll to test section
947
+ document.getElementById('test-api-btn')?.addEventListener('click', (e) => {
948
+ e.preventDefault();
949
+ document.getElementById('test-api').scrollIntoView({ behavior: 'smooth' });
 
 
 
 
950
  });
951
 
952
  // Add page load animation
 
957
  document.body.style.opacity = '1';
958
  }, 100);
959
  });
960
+
961
+ // Show welcome toast
962
+ setTimeout(() => {
963
+ showToast('Welcome to Portfolio API! πŸš€', 'info');
964
+ }, 1000);
965
  </script>
966
  </body>
967