Json026 commited on
Commit
89c1bd5
·
verified ·
1 Parent(s): 7a827b9

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +423 -210
index.html CHANGED
@@ -1,229 +1,442 @@
1
  <!DOCTYPE html>
2
- <html lang="en" class="scroll-smooth">
3
  <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
-
7
- <!-- SEO Meta Tags -->
8
- <title>DSA Odyssey | Problem Solving Portfolio</title>
9
- <meta name="description" content="A curated collection of Data Structures and Algorithms problems solved by [Your Name]. Featuring complexity analysis and clean code.">
10
- <meta property="og:title" content="DSA Odyssey Portfolio">
11
- <meta property="og:description" content="Explore my journey through 30+ DSA challenges with optimized solutions.">
12
- <meta property="og:type" content="website">
13
-
14
- <!-- Fonts & Icons -->
15
- <link rel="preconnect" href="https://fonts.googleapis.com">
16
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
17
- <script src="https://unpkg.com/lucide@latest"></script>
18
- <script src="https://cdn.tailwindcss.com"></script>
19
-
20
- <style>
21
- body { font-family: 'Inter', sans-serif; }
22
- .mono { font-family: 'JetBrains Mono', monospace; }
23
-
24
- /* Glassmorphism utility */
25
- .glass {
26
- background: rgba(255, 255, 255, 0.03);
27
- backdrop-filter: blur(12px);
28
- -webkit-backdrop-filter: blur(12px);
29
- border: 1px solid rgba(255, 255, 255, 0.1);
30
- }
31
 
32
- .dark .glass {
33
- background: rgba(0, 0, 0, 0.2);
34
- border: 1px solid rgba(255, 255, 255, 0.05);
35
- }
 
 
36
 
37
- /* Custom Scrollbar */
38
- ::-webkit-scrollbar { width: 8px; }
39
- ::-webkit-scrollbar-track { background: #0f172a; }
40
- ::-webkit-scrollbar-thumb { background: #334155; border-radius: 10px; }
41
- </style>
42
-
43
- <script>
44
- // Tailwind Config for Dark Mode
45
- tailwind.config = {
46
- darkMode: 'class',
47
- theme: {
48
- extend: {
49
- colors: {
50
- darkBg: '#020617',
51
- accent: '#3b82f6'
52
- }
53
- }
54
- }
55
- }
56
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  </head>
58
- <body class="bg-slate-50 dark:bg-darkBg text-slate-900 dark:text-slate-100 transition-colors duration-300">
59
-
60
- <!-- Navigation -->
61
- <nav class="sticky top-0 z-50 glass border-b border-slate-200 dark:border-slate-800 px-6 py-4">
62
- <div class="max-w-6xl mx-auto flex justify-between items-center">
63
- <div class="flex items-center gap-2">
64
- <i data-lucide="terminal" class="text-accent"></i>
65
- <span class="font-bold text-xl tracking-tight">DSA.Portfolio</span>
66
- </div>
67
- <button id="themeToggle" class="p-2 rounded-full hover:bg-slate-200 dark:hover:bg-slate-800 transition-colors">
68
- <i data-lucide="moon" id="themeIcon"></i>
69
- </button>
70
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  </nav>
 
72
 
73
- <main class="max-w-6xl mx-auto px-6 py-12">
74
- <!-- Hero Section -->
75
- <header class="mb-16">
76
- <h1 class="text-4xl md:text-6xl font-extrabold mb-4 bg-gradient-to-r from-slate-900 to-slate-500 dark:from-white dark:to-slate-500 bg-clip-text text-transparent">
77
- Mastering Algorithms.
78
- </h1>
79
- <p class="text-slate-500 dark:text-slate-400 max-w-2xl text-lg mb-8">
80
- A technical log of algorithmic challenges, complexity analysis, and efficient data structure implementations.
81
- </p>
82
-
83
- <!-- Progress Tracker -->
84
- <div class="max-w-xs">
85
- <div class="flex justify-between mb-2 text-sm font-medium">
86
- <span>Overall Progress</span>
87
- <span id="progressText">0/30</span>
88
- </div>
89
- <div class="w-full bg-slate-200 dark:bg-slate-800 h-2 rounded-full overflow-hidden">
90
- <div id="progressBar" class="bg-accent h-full transition-all duration-1000" style="width: 0%"></div>
91
- </div>
92
- </div>
93
- </header>
94
-
95
- <!-- Search and Filters -->
96
- <section class="mb-12 space-y-6">
97
- <div class="relative group">
98
- <i data-lucide="search" class="absolute left-4 top-1/2 -translate-y-1/2 text-slate-400 group-focus-within:text-accent transition-colors"></i>
99
- <input type="text" id="searchInput" placeholder="Search problems (e.g. 'Two Sum' or 'Graph')..."
100
- class="w-full bg-white dark:bg-slate-900/50 border border-slate-200 dark:border-slate-800 rounded-2xl py-4 pl-12 pr-4 focus:ring-2 focus:ring-accent outline-none transition-all shadow-sm">
101
- </div>
102
 
103
- <div class="flex flex-wrap gap-2" id="filterContainer">
104
- <button class="filter-btn active px-4 py-1.5 rounded-full text-sm font-medium border border-slate-200 dark:border-slate-800 transition-all bg-slate-900 text-white dark:bg-white dark:text-black" data-filter="all">All</button>
105
- <button class="filter-btn px-4 py-1.5 rounded-full text-sm font-medium border border-slate-200 dark:border-slate-800 hover:border-accent transition-all" data-filter="Easy">Easy</button>
106
- <button class="filter-btn px-4 py-1.5 rounded-full text-sm font-medium border border-slate-200 dark:border-slate-800 hover:border-accent transition-all" data-filter="Medium">Medium</button>
107
- <button class="filter-btn px-4 py-1.5 rounded-full text-sm font-medium border border-slate-200 dark:border-slate-800 hover:border-accent transition-all" data-filter="Hard">Hard</button>
108
- </div>
109
- </section>
110
-
111
- <!-- Problem Grid -->
112
- <div id="problemGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
113
- <!-- Skeleton Loading -->
114
- <div class="animate-pulse glass h-48 rounded-2xl"></div>
115
- <div class="animate-pulse glass h-48 rounded-2xl"></div>
116
- <div class="animate-pulse glass h-48 rounded-2xl"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  </div>
118
- </main>
119
-
120
- <footer class="border-t border-slate-200 dark:border-slate-800 py-12 text-center text-slate-500 text-sm">
121
- <p>© 2026 • Designed for high performance.</p>
122
- </footer>
123
-
124
- <script>
125
- // App State
126
- let problems = [];
127
- let currentFilter = 'all';
128
- let searchQuery = '';
129
-
130
- // Lucide Icons Initialization
131
- lucide.createIcons();
132
-
133
- // Theme Toggle Logic
134
- const themeToggle = document.getElementById('themeToggle');
135
- const html = document.documentElement;
136
-
137
- themeToggle.addEventListener('click', () => {
138
- html.classList.toggle('dark');
139
- const isDark = html.classList.contains('dark');
140
- themeToggle.querySelector('i').setAttribute('data-lucide', isDark ? 'sun' : 'moon');
141
- lucide.createIcons();
142
- });
143
 
144
- // Fetch Data
145
- async function fetchProblems() {
146
- try {
147
- // In a real scenario, use: const response = await fetch('data.json');
148
- // For this demo, I'll simulate the data directly if file is missing
149
- const data = [
150
- { "id": 1, "title": "Two Sum", "difficulty": "Easy", "topic": "Arrays", "url": "#" },
151
- { "id": 2, "title": "Longest Substring", "difficulty": "Medium", "topic": "Sliding Window", "url": "#" },
152
- { "id": 3, "title": "Merge K Sorted Lists", "difficulty": "Hard", "topic": "Heap", "url": "#" },
153
- { "id": 4, "title": "Valid Anagram", "difficulty": "Easy", "topic": "Hashing", "url": "#" },
154
- { "id": 5, "title": "Number of Islands", "difficulty": "Medium", "topic": "Graphs", "url": "#" }
155
- ];
156
- problems = data;
157
- updateUI();
158
- } catch (error) {
159
- console.error("Failed to fetch data:", error);
160
- }
161
- }
162
 
163
- function updateUI() {
164
- const grid = document.getElementById('problemGrid');
165
- const filtered = problems.filter(p => {
166
- const matchesFilter = currentFilter === 'all' || p.difficulty === currentFilter;
167
- const matchesSearch = p.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
168
- p.topic.toLowerCase().includes(searchQuery.toLowerCase());
169
- return matchesFilter && matchesSearch;
170
- });
171
-
172
- // Update Progress
173
- const total = 30;
174
- const solved = problems.length;
175
- document.getElementById('progressText').innerText = `${solved}/${total}`;
176
- document.getElementById('progressBar').style.width = `${(solved / total) * 100}%`;
177
-
178
- grid.innerHTML = filtered.map(p => `
179
- <article class="group glass p-6 rounded-2xl hover:border-accent/50 transition-all cursor-pointer flex flex-col justify-between">
180
- <div>
181
- <div class="flex justify-between items-start mb-4">
182
- <span class="text-xs font-bold uppercase tracking-widest px-2 py-1 rounded bg-slate-100 dark:bg-slate-800 ${getDiffClass(p.difficulty)}">
183
- ${p.difficulty}
184
- </span>
185
- <span class="text-slate-400 text-xs mono">#${p.id.toString().padStart(3, '0')}</span>
186
- </div>
187
- <h3 class="text-xl font-bold mb-2 group-hover:text-accent transition-colors">${p.title}</h3>
188
- <div class="flex items-center gap-2 text-slate-500 text-sm">
189
- <i data-lucide="tag" class="w-4 h-4"></i>
190
- <span>${p.topic}</span>
191
- </div>
192
- </div>
193
- <a href="${p.url}" class="mt-6 flex items-center justify-between text-sm font-semibold group-hover:translate-x-1 transition-transform">
194
- View Solution <i data-lucide="arrow-right" class="w-4 h-4"></i>
195
- </a>
196
- </article>
197
- `).join('');
198
-
199
- lucide.createIcons();
200
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
- function getDiffClass(diff) {
203
- if(diff === 'Easy') return 'text-emerald-500';
204
- if(diff === 'Medium') return 'text-amber-500';
205
- return 'text-rose-500';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  }
207
 
208
- // Event Listeners
209
- document.getElementById('searchInput').addEventListener('input', (e) => {
210
- searchQuery = e.target.value;
211
- updateUI();
212
- });
213
 
214
- document.getElementById('filterContainer').addEventListener('click', (e) => {
215
- if (e.target.classList.contains('filter-btn')) {
216
- document.querySelectorAll('.filter-btn').forEach(btn => {
217
- btn.classList.remove('bg-slate-900', 'text-white', 'dark:bg-white', 'dark:text-black');
218
- });
219
- e.target.classList.add('bg-slate-900', 'text-white', 'dark:bg-white', 'dark:text-black');
220
- currentFilter = e.target.dataset.filter;
221
- updateUI();
222
- }
223
  });
224
 
225
- // Initialize
226
- fetchProblems();
227
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  </body>
229
  </html>
 
1
  <!DOCTYPE html>
2
+ <html lang="en" class="dark">
3
  <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ <!-- SEO -->
8
+ <title>DSA Portfolio | Problem Solving Journey</title>
9
+ <meta
10
+ name="description"
11
+ content="A modern DSA Portfolio showcasing solved Data Structures & Algorithms problems with filters, search, progress tracking, and elegant UI."
12
+ />
13
 
14
+ <!-- Open Graph -->
15
+ <meta property="og:title" content="DSA Portfolio" />
16
+ <meta
17
+ property="og:description"
18
+ content="Track and showcase solved DSA problems with a modern portfolio."
19
+ />
20
+ <meta property="og:type" content="website" />
21
+ <meta property="og:image" content="https://dummyimage.com/1200x630/111827/ffffff&text=DSA+Portfolio" />
22
+
23
+ <!-- Fonts -->
24
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
25
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
26
+
27
+ <link
28
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap"
29
+ rel="stylesheet"
30
+ />
31
+
32
+ <!-- Tailwind -->
33
+ <script src="https://cdn.tailwindcss.com"></script>
34
+
35
+ <script>
36
+ tailwind.config = {
37
+ darkMode: "class",
38
+ theme: {
39
+ extend: {
40
+ fontFamily: {
41
+ inter: ["Inter", "sans-serif"],
42
+ mono: ["JetBrains Mono", "monospace"],
43
+ },
44
+ animation: {
45
+ float: "float 5s ease-in-out infinite",
46
+ },
47
+ keyframes: {
48
+ float: {
49
+ "0%, 100%": { transform: "translateY(0px)" },
50
+ "50%": { transform: "translateY(-8px)" },
51
+ },
52
+ },
53
+ },
54
+ },
55
+ };
56
+ </script>
57
+
58
+ <style>
59
+ ::-webkit-scrollbar {
60
+ width: 8px;
61
+ }
62
+
63
+ ::-webkit-scrollbar-thumb {
64
+ background: #6b7280;
65
+ border-radius: 999px;
66
+ }
67
+
68
+ html {
69
+ scroll-behavior: smooth;
70
+ }
71
+
72
+ body {
73
+ transition: background 0.3s ease;
74
+ }
75
+
76
+ .glass {
77
+ backdrop-filter: blur(14px);
78
+ -webkit-backdrop-filter: blur(14px);
79
+ }
80
+ </style>
81
  </head>
82
+
83
+ <body class="bg-gradient-to-br from-slate-100 via-white to-slate-200 dark:from-[#0b1120] dark:via-[#0f172a] dark:to-[#020617] text-slate-900 dark:text-white font-inter min-h-screen">
84
+
85
+ <!-- Decorative Blobs -->
86
+ <div class="fixed inset-0 overflow-hidden -z-10">
87
+ <div class="absolute top-10 left-10 w-72 h-72 bg-cyan-500/20 rounded-full blur-3xl animate-float"></div>
88
+ <div class="absolute bottom-10 right-10 w-72 h-72 bg-violet-500/20 rounded-full blur-3xl animate-float"></div>
89
+ </div>
90
+
91
+ <!-- Header -->
92
+ <header class="sticky top-0 z-50 border-b border-white/10 bg-white/10 dark:bg-white/5 glass">
93
+ <nav class="max-w-7xl mx-auto px-5 py-4 flex items-center justify-between">
94
+
95
+ <div>
96
+ <h1 class="text-2xl md:text-3xl font-extrabold tracking-tight">
97
+ DSA Portfolio
98
+ </h1>
99
+ <p class="text-sm text-slate-600 dark:text-slate-400 mt-1">
100
+ Track. Solve. Improve.
101
+ </p>
102
+ </div>
103
+
104
+ <button
105
+ id="themeToggle"
106
+ aria-label="Toggle Theme"
107
+ class="px-4 py-2 rounded-xl border border-white/10 bg-white/10 hover:bg-white/20 transition"
108
+ >
109
+ 🌙
110
+ </button>
111
  </nav>
112
+ </header>
113
 
114
+ <!-- Hero -->
115
+ <section class="max-w-7xl mx-auto px-5 pt-12 pb-8">
116
+ <div class="grid lg:grid-cols-2 gap-10 items-center">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
 
118
+ <div>
119
+ <span class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-cyan-400 text-sm font-medium">
120
+ 🚀 Data Structures & Algorithms
121
+ </span>
122
+
123
+ <h2 class="mt-6 text-5xl md:text-6xl font-black leading-tight">
124
+ Build Your
125
+ <span class="bg-gradient-to-r from-cyan-400 to-violet-400 bg-clip-text text-transparent">
126
+ Coding Journey
127
+ </span>
128
+ </h2>
129
+
130
+ <p class="mt-6 text-lg text-slate-600 dark:text-slate-400 leading-relaxed max-w-2xl">
131
+ A modern portfolio showcasing solved DSA problems with filtering,
132
+ searching, progress tracking, and elegant UI inspired by modern developer tools.
133
+ </p>
134
+
135
+ <!-- Progress -->
136
+ <div class="mt-8 max-w-xl">
137
+ <div class="flex items-center justify-between mb-2">
138
+ <span class="text-sm font-medium text-slate-700 dark:text-slate-300">
139
+ Programs Solved
140
+ </span>
141
+
142
+ <span
143
+ id="progressText"
144
+ class="font-mono text-cyan-400"
145
+ >
146
+ 0/30
147
+ </span>
148
+ </div>
149
+
150
+ <div class="w-full h-3 bg-white/10 rounded-full overflow-hidden">
151
+ <div
152
+ id="progressBar"
153
+ class="h-full bg-gradient-to-r from-cyan-400 to-violet-500 rounded-full transition-all duration-500"
154
+ style="width: 0%"
155
+ ></div>
156
+ </div>
157
  </div>
158
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
+ <!-- Stats Card -->
161
+ <div class="glass border border-white/10 bg-white/10 dark:bg-white/5 rounded-3xl p-8 shadow-2xl">
162
+ <div class="grid grid-cols-2 gap-5">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
+ <div class="p-5 rounded-2xl bg-white/10 border border-white/10">
165
+ <h3 class="text-sm text-slate-400">Total Problems</h3>
166
+ <p id="totalProblems" class="text-4xl font-black mt-2">0</p>
167
+ </div>
168
+
169
+ <div class="p-5 rounded-2xl bg-white/10 border border-white/10">
170
+ <h3 class="text-sm text-slate-400">Topics Covered</h3>
171
+ <p id="topicsCount" class="text-4xl font-black mt-2">0</p>
172
+ </div>
173
+
174
+ <div class="p-5 rounded-2xl bg-white/10 border border-white/10">
175
+ <h3 class="text-sm text-slate-400">Easy</h3>
176
+ <p id="easyCount" class="text-4xl font-black mt-2 text-green-400">0</p>
177
+ </div>
178
+
179
+ <div class="p-5 rounded-2xl bg-white/10 border border-white/10">
180
+ <h3 class="text-sm text-slate-400">Medium/Hard</h3>
181
+ <p id="mediumHardCount" class="text-4xl font-black mt-2 text-orange-400">0</p>
182
+ </div>
183
+
184
+ </div>
185
+ </div>
186
+
187
+ </div>
188
+ </section>
189
+
190
+ <!-- Main -->
191
+ <main class="max-w-7xl mx-auto px-5 pb-16">
192
+
193
+ <!-- Controls -->
194
+ <section class="mb-10">
195
+
196
+ <!-- Search -->
197
+ <div class="relative mb-6">
198
+ <input
199
+ type="text"
200
+ id="searchInput"
201
+ placeholder="Search problems by name..."
202
+ class="w-full px-5 py-4 rounded-2xl bg-white/10 dark:bg-white/5 border border-white/10 glass outline-none focus:ring-2 focus:ring-cyan-400 text-lg placeholder:text-slate-500"
203
+ />
204
+
205
+ <span class="absolute right-5 top-1/2 -translate-y-1/2 text-slate-400">
206
+ 🔍
207
+ </span>
208
+ </div>
209
+
210
+ <!-- Filter Chips -->
211
+ <div id="filterContainer" class="flex flex-wrap gap-3">
212
+ </div>
213
+
214
+ </section>
215
+
216
+ <!-- Problem Grid -->
217
+ <section>
218
+ <div
219
+ id="problemGrid"
220
+ class="grid sm:grid-cols-2 xl:grid-cols-3 gap-6"
221
+ >
222
+ </div>
223
+ </section>
224
+
225
+ </main>
226
+
227
+ <!-- Footer -->
228
+ <footer class="border-t border-white/10 py-8 text-center text-slate-500">
229
+ <p>
230
+ Built with ❤️ using HTML, Tailwind CSS & Vanilla JavaScript
231
+ </p>
232
+ </footer>
233
+
234
+ <script>
235
+ const problemGrid = document.getElementById("problemGrid");
236
+ const searchInput = document.getElementById("searchInput");
237
+ const filterContainer = document.getElementById("filterContainer");
238
+ const progressBar = document.getElementById("progressBar");
239
+ const progressText = document.getElementById("progressText");
240
+
241
+ const totalProblems = document.getElementById("totalProblems");
242
+ const topicsCount = document.getElementById("topicsCount");
243
+ const easyCount = document.getElementById("easyCount");
244
+ const mediumHardCount = document.getElementById("mediumHardCount");
245
+
246
+ let problems = [];
247
+ let activeFilter = "All";
248
 
249
+ // Theme Toggle
250
+ const themeToggle = document.getElementById("themeToggle");
251
+
252
+ themeToggle.addEventListener("click", () => {
253
+ document.documentElement.classList.toggle("dark");
254
+
255
+ if (document.documentElement.classList.contains("dark")) {
256
+ themeToggle.textContent = "🌙";
257
+ } else {
258
+ themeToggle.textContent = "☀️";
259
+ }
260
+ });
261
+
262
+ // Fetch JSON Data
263
+ async function fetchProblems() {
264
+ try {
265
+ const response = await fetch("./data.json");
266
+ problems = await response.json();
267
+
268
+ renderStats();
269
+ renderFilters();
270
+ renderProblems(problems);
271
+
272
+ } catch (error) {
273
+ console.error("Error loading JSON:", error);
274
+
275
+ problemGrid.innerHTML = `
276
+ <div class="col-span-full text-center py-20">
277
+ <h2 class="text-3xl font-bold text-red-400">
278
+ Failed to load data.json
279
+ </h2>
280
+ </div>
281
+ `;
282
+ }
283
+ }
284
+
285
+ // Render Stats
286
+ function renderStats() {
287
+ totalProblems.textContent = problems.length;
288
+
289
+ const uniqueTopics = [...new Set(problems.map(p => p.topic))];
290
+ topicsCount.textContent = uniqueTopics.length;
291
+
292
+ const easy = problems.filter(p => p.difficulty === "Easy").length;
293
+ easyCount.textContent = easy;
294
+
295
+ mediumHardCount.textContent = problems.length - easy;
296
+
297
+ const solved = problems.length;
298
+ const target = 30;
299
+
300
+ progressText.textContent = `${solved}/${target}`;
301
+
302
+ const percentage = Math.min((solved / target) * 100, 100);
303
+ progressBar.style.width = `${percentage}%`;
304
+ }
305
+
306
+ // Create Filters
307
+ function renderFilters() {
308
+ const difficulties = [...new Set(problems.map(p => p.difficulty))];
309
+ const topics = [...new Set(problems.map(p => p.topic))];
310
+
311
+ const filters = ["All", ...difficulties, ...topics];
312
+
313
+ filters.forEach(filter => {
314
+ const btn = document.createElement("button");
315
+
316
+ btn.textContent = filter;
317
+
318
+ btn.className =
319
+ "px-4 py-2 rounded-full border border-white/10 bg-white/10 hover:bg-cyan-500 hover:text-white transition text-sm font-medium";
320
+
321
+ if (filter === "All") {
322
+ btn.classList.add("bg-cyan-500", "text-white");
323
  }
324
 
325
+ btn.addEventListener("click", () => {
326
+ activeFilter = filter;
327
+
328
+ document.querySelectorAll("#filterContainer button")
329
+ .forEach(b => b.classList.remove("bg-cyan-500", "text-white"));
330
 
331
+ btn.classList.add("bg-cyan-500", "text-white");
332
+
333
+ filterProblems();
 
 
 
 
 
 
334
  });
335
 
336
+ filterContainer.appendChild(btn);
337
+ });
338
+ }
339
+
340
+ // Filter Logic
341
+ function filterProblems() {
342
+ const searchValue = searchInput.value.toLowerCase();
343
+
344
+ const filtered = problems.filter(problem => {
345
+ const matchesSearch =
346
+ problem.title.toLowerCase().includes(searchValue);
347
+
348
+ const matchesFilter =
349
+ activeFilter === "All" ||
350
+ problem.difficulty === activeFilter ||
351
+ problem.topic === activeFilter;
352
+
353
+ return matchesSearch && matchesFilter;
354
+ });
355
+
356
+ renderProblems(filtered);
357
+ }
358
+
359
+ // Search
360
+ searchInput.addEventListener("input", filterProblems);
361
+
362
+ // Difficulty Badge Colors
363
+ function getDifficultyColor(level) {
364
+ if (level === "Easy") {
365
+ return "bg-green-500/15 text-green-400 border-green-500/20";
366
+ }
367
+
368
+ if (level === "Medium") {
369
+ return "bg-yellow-500/15 text-yellow-400 border-yellow-500/20";
370
+ }
371
+
372
+ return "bg-red-500/15 text-red-400 border-red-500/20";
373
+ }
374
+
375
+ // Render Problems
376
+ function renderProblems(data) {
377
+ problemGrid.innerHTML = "";
378
+
379
+ if (data.length === 0) {
380
+ problemGrid.innerHTML = `
381
+ <div class="col-span-full text-center py-20">
382
+ <h2 class="text-3xl font-bold">
383
+ No Problems Found 😢
384
+ </h2>
385
+ </div>
386
+ `;
387
+ return;
388
+ }
389
+
390
+ data.forEach(problem => {
391
+ const card = document.createElement("article");
392
+
393
+ card.className =
394
+ "group glass border border-white/10 bg-white/10 dark:bg-white/5 rounded-3xl p-6 hover:-translate-y-2 transition duration-300 shadow-xl";
395
+
396
+ card.innerHTML = `
397
+ <div class="flex items-start justify-between gap-4">
398
+
399
+ <div>
400
+ <span class="font-mono text-xs text-cyan-400">
401
+ ${problem.topic}
402
+ </span>
403
+
404
+ <h2 class="mt-3 text-2xl font-bold leading-tight group-hover:text-cyan-400 transition">
405
+ ${problem.title}
406
+ </h2>
407
+ </div>
408
+
409
+ <span class="px-3 py-1 rounded-full text-xs border ${getDifficultyColor(problem.difficulty)}">
410
+ ${problem.difficulty}
411
+ </span>
412
+
413
+ </div>
414
+
415
+ <div class="mt-8 flex items-center justify-between">
416
+
417
+ <a
418
+ href="${problem.url}"
419
+ target="_blank"
420
+ rel="noopener noreferrer"
421
+ class="inline-flex items-center gap-2 px-5 py-3 rounded-xl bg-gradient-to-r from-cyan-500 to-violet-500 text-white font-semibold hover:scale-105 transition"
422
+ aria-label="Open ${problem.title}"
423
+ >
424
+ Solve Problem →
425
+ </a>
426
+
427
+ <div class="text-sm text-slate-400 font-mono">
428
+ #DSA
429
+ </div>
430
+
431
+ </div>
432
+ `;
433
+
434
+ problemGrid.appendChild(card);
435
+ });
436
+ }
437
+
438
+ // Initialize
439
+ fetchProblems();
440
+ </script>
441
  </body>
442
  </html>