@@ -38,31 +38,107 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
3838 ))}
3939</section >
4040
41- <!-- Client-side JavaScript disabled to preserve server-side rendering -->
41+ <script >
42+ // Get all projects data from the server-rendered content
43+ const projectList = Array.from(document.querySelectorAll('.Card-Container')).map(card => {
44+ const link = card.querySelector('.Card-Real-Link');
45+ const title = card.querySelector('.Card-Title');
46+ const description = card.querySelector('.Card-Description p');
47+ const tags = Array.from(card.querySelectorAll('.Card-Tag p')).map(tag => tag.textContent);
48+ const logo = card.querySelector('.Project-Logo');
49+
50+ return {
51+ name: title?.textContent || '',
52+ projectLink: link?.href || '',
53+ description: description?.textContent || '',
54+ tags: tags,
55+ imageSrc: logo?.src || '',
56+ element: card // Keep reference to original element
57+ };
58+ });
59+
60+ // Initialize variables
61+ let filteredProjects = [...projectList];
62+ let searchValue = '';
63+ let selectedTags = [];
64+
65+ // DOM elements
66+ const searchInput = document.getElementById('search');
67+ const tagSelector = document.getElementById('tag-selector');
68+ const projectListContainer = document.getElementById('project-list');
69+
70+ // Filter projects function
71+ function filterProjects() {
72+ let filtered = [...projectList];
73+
74+ // Filter by search term
75+ if (searchValue.trim()) {
76+ const searchTerm = searchValue.toLowerCase();
77+ filtered = filtered.filter(project =>
78+ project.name.toLowerCase().includes(searchTerm) ||
79+ project.description.toLowerCase().includes(searchTerm) ||
80+ (project.tags && project.tags.some(tag => tag.toLowerCase().includes(searchTerm)))
81+ );
82+ }
83+
84+ // Filter by tags
85+ if (selectedTags.length > 0) {
86+ filtered = filtered.filter(project =>
87+ project.tags && project.tags.some(tag =>
88+ selectedTags.includes(tag.toLowerCase())
89+ )
90+ );
91+ }
92+
93+ filteredProjects = filtered;
94+
95+ // Hide/show cards instead of re-rendering
96+ projectList.forEach(project => {
97+ const isVisible = filteredProjects.includes(project);
98+ project.element.style.display = isVisible ? 'block' : 'none';
99+ });
100+ }
101+
102+ // Event listeners
103+ searchInput.addEventListener('input', (e) => {
104+ searchValue = e.target.value;
105+ filterProjects();
106+ });
107+
108+ tagSelector.addEventListener('change', (e) => {
109+ selectedTags = e.target.value ? [e.target.value] : [];
110+ filterProjects();
111+ });
112+
113+ // Initial filter (show all)
114+ filterProjects();
115+ </script >
42116
43117<style >
44118 #container {
45119 display: flex;
46- gap: 1rem;
47- margin-bottom: 2rem;
120+ gap: 4rem;
121+ margin: 2rem 0 3rem 0;
122+ padding: 1.5rem;
48123 flex-wrap: wrap;
49124 justify-content: center;
50125 }
51126
52127 .inputContainer {
53128 flex: 1;
54- min-width: 200px ;
129+ min-width: 250px ;
55130 }
56131
57132 #search {
58133 width: 100%;
59- padding: 0.75rem 1rem;
134+ padding: 1rem 1.25rem ;
60135 border: 1px solid rgba(255, 255, 255, 0.2);
61- border-radius: 8px ;
136+ border-radius: 10px ;
62137 background: rgba(255, 255, 255, 0.1);
63138 color: white;
64139 font-size: 1rem;
65140 backdrop-filter: blur(10px);
141+ transition: all 0.3s ease;
66142 }
67143
68144 #search::placeholder {
@@ -77,13 +153,14 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
77153
78154 #tag-selector {
79155 width: 100%;
80- padding: 0.75rem 1rem;
156+ padding: 1rem 1.25rem ;
81157 border: 1px solid rgba(255, 255, 255, 0.2);
82- border-radius: 8px ;
158+ border-radius: 10px ;
83159 background: rgba(255, 255, 255, 0.1);
84160 color: white;
85161 font-size: 1rem;
86162 backdrop-filter: blur(10px);
163+ transition: all 0.3s ease;
87164 }
88165
89166 #tag-selector:focus {
@@ -107,11 +184,24 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
107184 @media (max-width: 768px) {
108185 #container {
109186 flex-direction: column;
187+ gap: 1rem;
188+ padding: 1rem;
189+ margin: 1rem 0 2rem 0;
190+ }
191+
192+ .inputContainer {
193+ min-width: unset;
194+ }
195+
196+ #search, #tag-selector {
197+ padding: 0.875rem 1rem;
198+ font-size: 0.95rem;
110199 }
111200
112201 .containerLayout {
113202 grid-template-columns: 1fr;
114203 gap: 1rem;
204+ padding: 0 0.5rem;
115205 }
116206 }
117207</style >
0 commit comments